Import rust-debcargo_2.7.11.orig.tar.gz
authorFabian Grünbichler <debian@fabian.gruenbichler.email>
Wed, 1 Oct 2025 18:24:55 +0000 (20:24 +0200)
committerFabian Grünbichler <debian@fabian.gruenbichler.email>
Wed, 1 Oct 2025 18:24:55 +0000 (20:24 +0200)
[dgit import orig rust-debcargo_2.7.11.orig.tar.gz]

290 files changed:
.cargo_vcs_info.json [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.gitlab-ci.yml [new file with mode: 0644]
Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
Cargo.toml.orig [new file with mode: 0644]
HACKING.md [new file with mode: 0644]
README.md [new file with mode: 0644]
TODO.md [new file with mode: 0644]
debcargo.toml.example [new file with mode: 0644]
manpages/debcargo-build-order.1 [new file with mode: 0644]
manpages/debcargo-deb-dependencies.1 [new file with mode: 0644]
manpages/debcargo-deb-src-name.1 [new file with mode: 0644]
manpages/debcargo-extract.1 [new file with mode: 0644]
manpages/debcargo-package.1 [new file with mode: 0644]
manpages/debcargo-update.1 [new file with mode: 0644]
manpages/debcargo.1 [new file with mode: 0644]
src/bin/debcargo.rs [new file with mode: 0644]
src/build_order.rs [new file with mode: 0644]
src/cli.rs [new file with mode: 0644]
src/config.rs [new file with mode: 0644]
src/crates.rs [new file with mode: 0644]
src/deb_dependencies.rs [new file with mode: 0644]
src/debian/changelog.rs [new file with mode: 0644]
src/debian/changelog/tests.rs [new file with mode: 0644]
src/debian/control.rs [new file with mode: 0644]
src/debian/control/tests.rs [new file with mode: 0644]
src/debian/copyright.rs [new file with mode: 0644]
src/debian/copyright/tests.rs [new file with mode: 0644]
src/debian/dependency.rs [new file with mode: 0644]
src/debian/dependency/tests.rs [new file with mode: 0644]
src/debian/licenses/AGPL-3.0 [new file with mode: 0644]
src/debian/licenses/Apache-2.0 [new file with mode: 0644]
src/debian/licenses/BSD-2-Clause [new file with mode: 0644]
src/debian/licenses/BSD-3-Clause [new file with mode: 0644]
src/debian/licenses/CC0-1.0 [new file with mode: 0644]
src/debian/licenses/GPL-2.0 [new file with mode: 0644]
src/debian/licenses/GPL-3.0 [new file with mode: 0644]
src/debian/licenses/ISC [new file with mode: 0644]
src/debian/licenses/LGPL-2.0 [new file with mode: 0644]
src/debian/licenses/LGPL-2.1 [new file with mode: 0644]
src/debian/licenses/LGPL-3.0 [new file with mode: 0644]
src/debian/licenses/MIT [new file with mode: 0644]
src/debian/licenses/MITNFA [new file with mode: 0644]
src/debian/licenses/MPL-1.1 [new file with mode: 0644]
src/debian/licenses/MPL-2.0 [new file with mode: 0644]
src/debian/licenses/Unlicense [new file with mode: 0644]
src/debian/licenses/Zlib [new file with mode: 0644]
src/debian/mod.rs [new file with mode: 0644]
src/errors.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
src/package.rs [new file with mode: 0644]
src/util.rs [new file with mode: 0644]
tests/clap_override.toml [new file with mode: 0644]
tests/config_tests.rs [new file with mode: 0644]
tests/configs/aesni-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/aesni-0.10/debian/rules [new file with mode: 0644]
tests/configs/aesni/debian/debcargo.toml [new file with mode: 0644]
tests/configs/aesni/debian/rules [new file with mode: 0644]
tests/configs/afl-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/afl-0.10/debian/rules [new file with mode: 0644]
tests/configs/afl-0.13/debian/debcargo.toml [new file with mode: 0644]
tests/configs/afl-0.13/debian/rules [new file with mode: 0644]
tests/configs/aom-sys-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ascii-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ascii-0.8/debian/patches/fix-old-dep.patch [new file with mode: 0644]
tests/configs/ascii-0.8/debian/patches/series [new file with mode: 0644]
tests/configs/aws-lc-fips-sys-0.12/debian/debcargo.toml [new file with mode: 0644]
tests/configs/aws-lc-fips-sys-0.12/debian/rules [new file with mode: 0644]
tests/configs/blas-src-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/blas-src-0.6/debian/patches/drop-accelerate.diff [new file with mode: 0644]
tests/configs/blas-src-0.6/debian/patches/series [new file with mode: 0644]
tests/configs/broken-dh-strip/debian/debcargo.toml [new file with mode: 0644]
tests/configs/broken-dh-strip/debian/rules [new file with mode: 0755]
tests/configs/broken-lto/debian/debcargo.toml [new file with mode: 0644]
tests/configs/broken-lto/debian/rules [new file with mode: 0644]
tests/configs/broken-upstream/debian/debcargo.toml [new file with mode: 0644]
tests/configs/broken-upstream/debian/rules [new file with mode: 0644]
tests/configs/brotli-decompressor-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/brotli-decompressor-2/debian/rules [new file with mode: 0644]
tests/configs/clang-sys-0.23/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clang-sys-0.26/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clang-sys-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clang-sys/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clippy-0.0/debian/debcargo.toml [new file with mode: 0644]
tests/configs/clippy-0.0/debian/rules [new file with mode: 0644]
tests/configs/cmake-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiler-builtins-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiler-builtins-0.1/debian/rules [new file with mode: 0644]
tests/configs/compiler-error-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiler-error-0.1/debian/rules [new file with mode: 0644]
tests/configs/compiletest-rs-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/compiletest-rs-0.3/debian/rules [new file with mode: 0644]
tests/configs/core-arch-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-arch-0.1/debian/rules [new file with mode: 0644]
tests/configs/core-error-0.0/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-error-0.0/debian/rules [new file with mode: 0644]
tests/configs/core-extensions-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-extensions-0.1/debian/rules [new file with mode: 0644]
tests/configs/core-foundation-0.9/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-foundation-0.9/debian/rules [new file with mode: 0644]
tests/configs/core-graphics-0.23/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-graphics-0.23/debian/rules [new file with mode: 0644]
tests/configs/core-graphics-types-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-graphics-types-0.1/debian/rules [new file with mode: 0644]
tests/configs/core-text-20/debian/debcargo.toml [new file with mode: 0644]
tests/configs/core-text-20/debian/rules [new file with mode: 0644]
tests/configs/cpp-demangle-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/dav1d-sys-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/dav1d-sys-0.3/debian/patches/relax-bindgen.patch [new file with mode: 0644]
tests/configs/dav1d-sys-0.3/debian/patches/series [new file with mode: 0644]
tests/configs/dav1d-sys-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/derive-builder-0.9/debian/debcargo.toml [new file with mode: 0644]
tests/configs/derive-builder-0.9/debian/rules [new file with mode: 0644]
tests/configs/diesel-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/diesel-1/debian/patches/fix-old-dep.patch [new file with mode: 0644]
tests/configs/diesel-1/debian/patches/series [new file with mode: 0644]
tests/configs/diesel-derives-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/diesel-derives-2/debian/rules [new file with mode: 0644]
tests/configs/dwrote-0.11/debian/debcargo.toml [new file with mode: 0644]
tests/configs/dwrote-0.11/debian/rules [new file with mode: 0644]
tests/configs/exa-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/exa-0.10/debian/rules [new file with mode: 0644]
tests/configs/exa/debian/debcargo.toml [new file with mode: 0644]
tests/configs/exa/debian/rules [new file with mode: 0644]
tests/configs/fd-find-8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/fd-find-8/debian/rules [new file with mode: 0644]
tests/configs/fsevent-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/fsevent-0.4/debian/rules [new file with mode: 0644]
tests/configs/fsevent-sys-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/fsevent-sys-2/debian/rules [new file with mode: 0644]
tests/configs/heapsize-plugin-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/heapsize-plugin-0.1/debian/rules [new file with mode: 0644]
tests/configs/http-types-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/http-types-2/debian/patches/fix-features.patch [new file with mode: 0644]
tests/configs/http-types-2/debian/patches/series [new file with mode: 0644]
tests/configs/hyperx-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/hyperx-1/debian/patches/relax-percent-encoding.patch [new file with mode: 0644]
tests/configs/hyperx-1/debian/patches/series [new file with mode: 0644]
tests/configs/hyperx/debian/debcargo.toml [new file with mode: 0644]
tests/configs/hyperx/debian/patches/relax-percent-encoding.patch [new file with mode: 0644]
tests/configs/hyperx/debian/patches/series [new file with mode: 0644]
tests/configs/iana-time-zone-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/iana-time-zone-0.1/debian/patches/fix-windows-dep.patch [new file with mode: 0644]
tests/configs/iana-time-zone-0.1/debian/patches/series [new file with mode: 0644]
tests/configs/jetscii-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/jetscii-0.3/debian/rules [new file with mode: 0644]
tests/configs/kqueue-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/kqueue-1/debian/rules [new file with mode: 0644]
tests/configs/kqueue-sys-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/kqueue-sys-1/debian/rules [new file with mode: 0644]
tests/configs/libdav1d-sys-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/libdbus-sys-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/mysqlclient-src-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/mysqlclient-sys-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/mysqlclient-sys-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nasm-rs-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/netlib-src-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nodrop-union-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nodrop-union-0.1/debian/rules [new file with mode: 0644]
tests/configs/nom-4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/nom-4/debian/rules [new file with mode: 0644]
tests/configs/old-version/debian/debcargo.toml [new file with mode: 0644]
tests/configs/once-cell-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/onig-6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/onig-6/debian/rules [new file with mode: 0644]
tests/configs/onig-sys-69/debian/debcargo.toml [new file with mode: 0644]
tests/configs/onig-sys-69/debian/rules [new file with mode: 0644]
tests/configs/only-macos/debian/debcargo.toml [new file with mode: 0644]
tests/configs/only-macos/debian/rules [new file with mode: 0644]
tests/configs/only-windows/debian/debcargo.toml [new file with mode: 0644]
tests/configs/only-windows/debian/rules [new file with mode: 0644]
tests/configs/openssl-sys-0.9/debian/debcargo.toml [new file with mode: 0644]
tests/configs/openssl-sys-0.9/debian/patches/disable-bssl.patch [new file with mode: 0644]
tests/configs/openssl-sys-0.9/debian/patches/series [new file with mode: 0644]
tests/configs/packed-simd-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/packed-simd-0.3/debian/rules [new file with mode: 0644]
tests/configs/packed-simd-2-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/packed-simd-2-0.3/debian/rules [new file with mode: 0644]
tests/configs/petgraph-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/petgraph-0.4/debian/patches/fix-old-dep.patch [new file with mode: 0644]
tests/configs/petgraph-0.4/debian/patches/series [new file with mode: 0644]
tests/configs/phf-generator-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/pkg-config-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rav1e-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rav1e-0.6/debian/patches/relax-clap.diff [new file with mode: 0644]
tests/configs/rav1e-0.6/debian/patches/series [new file with mode: 0644]
tests/configs/redis-0.17/debian/debcargo.toml [new file with mode: 0644]
tests/configs/redis-0.17/debian/rules [new file with mode: 0644]
tests/configs/redox-syscall-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/redox-syscall-0.1/debian/rules [new file with mode: 0644]
tests/configs/redox-users-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/redox-users-0.3/debian/rules [new file with mode: 0644]
tests/configs/rhai-1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rhai-1/debian/rules [new file with mode: 0644]
tests/configs/ring-0.13/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ring-0.13/debian/rules [new file with mode: 0644]
tests/configs/ring-0.14/debian/debcargo.toml [new file with mode: 0644]
tests/configs/ring-0.14/debian/rules [new file with mode: 0644]
tests/configs/rust-hawktracer-sys-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/rust-hawktracer-sys-0.4/debian/rules [new file with mode: 0644]
tests/configs/rust-lzma-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/salvo-extra-0.16/debian/debcargo.toml [new file with mode: 0644]
tests/configs/salvo-extra-0.16/debian/rules [new file with mode: 0644]
tests/configs/security-framework-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/security-framework-2/debian/rules [new file with mode: 0644]
tests/configs/security-framework-sys-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/security-framework-sys-2/debian/rules [new file with mode: 0644]
tests/configs/serde-qs-0.8/debian/debcargo.toml [new file with mode: 0644]
tests/configs/serde-qs-0.8/debian/patches/fix-actix-web-dep.patch [new file with mode: 0644]
tests/configs/serde-qs-0.8/debian/patches/series [new file with mode: 0644]
tests/configs/servo-fontconfig-sys-5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/sleef-sys-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/sleef-sys-0.1/debian/rules [new file with mode: 0644]
tests/configs/spin-0.4/debian/debcargo.toml [new file with mode: 0644]
tests/configs/spin-0.4/debian/rules [new file with mode: 0644]
tests/configs/structopt-0.3/debian/debcargo.toml [new file with mode: 0644]
tests/configs/structopt-0.3/debian/patches/disable-lint-feature.diff [new file with mode: 0644]
tests/configs/structopt-0.3/debian/patches/disable-paw.diff [new file with mode: 0644]
tests/configs/structopt-0.3/debian/patches/series [new file with mode: 0644]
tests/configs/system-configuration-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-0.5/debian/rules [new file with mode: 0644]
tests/configs/system-configuration-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-0.6/debian/rules [new file with mode: 0644]
tests/configs/system-configuration-sys-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-sys-0.5/debian/rules [new file with mode: 0644]
tests/configs/system-configuration-sys-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-configuration-sys-0.6/debian/rules [new file with mode: 0644]
tests/configs/system-deps-6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/system-deps-6/debian/rules [new file with mode: 0755]
tests/configs/tiny-keccak-2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/tiny-keccak-2/debian/rules [new file with mode: 0644]
tests/configs/vcpkg-0.2/debian/debcargo.toml [new file with mode: 0644]
tests/configs/wepoll-ffi-0.1/debian/debcargo.toml [new file with mode: 0644]
tests/configs/wepoll-ffi-0.1/debian/rules [new file with mode: 0644]
tests/configs/windows-0.32/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.32/debian/rules [new file with mode: 0644]
tests/configs/windows-0.48/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.48/debian/rules [new file with mode: 0644]
tests/configs/windows-0.54/debian/changelog [new file with mode: 0644]
tests/configs/windows-0.54/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.54/debian/patches/remove-cycles.patch [new file with mode: 0644]
tests/configs/windows-0.54/debian/patches/series [new file with mode: 0644]
tests/configs/windows-0.54/debian/rules [new file with mode: 0644]
tests/configs/windows-0.54/debian/rules.debcargo.hint [new file with mode: 0755]
tests/configs/windows-0.58/debian/changelog [new file with mode: 0644]
tests/configs/windows-0.58/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-0.58/debian/patches/remove-cycles.patch [new file with mode: 0644]
tests/configs/windows-0.58/debian/patches/remove-cycles.patch~ [new file with mode: 0644]
tests/configs/windows-0.58/debian/patches/series [new file with mode: 0644]
tests/configs/windows-0.58/debian/rules [new file with mode: 0644]
tests/configs/windows-0.58/debian/rules.debcargo.hint [new file with mode: 0755]
tests/configs/windows-i686-gnullvm-0.52/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-i686-gnullvm-0.52/debian/rules [new file with mode: 0755]
tests/configs/windows-sys-0.59/debian/changelog [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/patches/remove-cycles.patch [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/patches/series [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/rules [new file with mode: 0644]
tests/configs/windows-sys-0.59/debian/rules.debcargo.hint [new file with mode: 0755]
tests/configs/windows-x86-64-gnullvm-0.42/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-x86-64-gnullvm-0.42/debian/rules [new file with mode: 0755]
tests/configs/windows-x86-64-gnullvm-0.48/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-x86-64-gnullvm-0.48/debian/rules [new file with mode: 0755]
tests/configs/windows-x86-64-gnullvm-0.52/debian/debcargo.toml [new file with mode: 0644]
tests/configs/windows-x86-64-gnullvm-0.52/debian/rules [new file with mode: 0755]
tests/configs/winreg-0.10/debian/debcargo.toml [new file with mode: 0644]
tests/configs/winreg-0.10/debian/rules [new file with mode: 0644]
tests/configs/winreg-0.50/debian/debcargo.toml [new file with mode: 0644]
tests/configs/winreg-0.50/debian/rules [new file with mode: 0644]
tests/configs/winreg-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/winreg-0.6/debian/rules [new file with mode: 0644]
tests/configs/x86-0.33/debian/debcargo.toml [new file with mode: 0644]
tests/configs/x86-0.33/debian/rules [new file with mode: 0644]
tests/configs/yeslogic-fontconfig-sys-6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/zip-0.5/debian/debcargo.toml [new file with mode: 0644]
tests/configs/zip-0.6/debian/debcargo.toml [new file with mode: 0644]
tests/configs/zip/debian/debcargo.toml [new file with mode: 0644]
tests/debcargo_override.toml [new file with mode: 0644]
tests/debcargo_override_top_level.toml [new file with mode: 0644]
tests/foobar-overlay/debian/debcargo.toml [new file with mode: 0644]
tests/foobar-semver-overlay/debian/debcargo.toml [new file with mode: 0644]
tests/foobar-semver.expected [new file with mode: 0644]
tests/foobar.expected [new file with mode: 0644]
tests/local-crate.rs [new file with mode: 0644]
tests/manpages.rs [new file with mode: 0644]
tests/sh/integrate.sh [new file with mode: 0755]
tests/sh/lintian-suppress-tags [new file with mode: 0644]
tests/sh/quick-build.sh [new file with mode: 0755]
tests/tiny-dfr_override.toml [new file with mode: 0644]

diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644 (file)
index 0000000..ec627d5
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "f828c1d0bee98bc4c29f46bcf8d4653fce619b29"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8f6d9c7
--- /dev/null
@@ -0,0 +1,10 @@
+/target
+/tmp
+
+/tests/foobar/target
+/tests/foobar-semver/target
+
+# editor files
+*~
+.idea/
+*.kdev4
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644 (file)
index 0000000..dfe9ac3
--- /dev/null
@@ -0,0 +1,20 @@
+image: "rust:latest"
+
+test:cargo:
+  script:
+    - rustc --version && cargo --version  # Print version info for debugging
+    - cargo test --workspace --verbose
+
+test:clippy:
+  stage: test
+  before_script:
+    - rustup component add clippy
+  script:
+    - cargo clippy
+
+test:format-code:
+  stage: test
+  before_script:
+    - rustup component add rustfmt
+  script:
+    - cargo fmt -- --check
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..32ecf06
--- /dev/null
@@ -0,0 +1,3615 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "ahash"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "allocator-api2"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "annotate-snippets"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991"
+dependencies = [
+ "anstyle",
+ "unicode-width 0.1.14",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
+[[package]]
+name = "arc-swap"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
+
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
+[[package]]
+name = "autocfg"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+
+[[package]]
+name = "base16ct"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "bitmaps"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "blake3"
+version = "1.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bstr"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+dependencies = [
+ "memchr",
+ "regex-automata 0.4.9",
+ "serde",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "bytes"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
+
+[[package]]
+name = "bytesize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
+
+[[package]]
+name = "cargo"
+version = "0.86.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62fdf5dbde4bf8d8149a4d32568d28d92af9dc4a4975727d89bd8dfb69fb810e"
+dependencies = [
+ "annotate-snippets",
+ "anstream",
+ "anstyle",
+ "anyhow",
+ "base64",
+ "blake3",
+ "bytesize",
+ "cargo-credential",
+ "cargo-credential-libsecret",
+ "cargo-credential-macos-keychain",
+ "cargo-credential-wincred",
+ "cargo-platform",
+ "cargo-util",
+ "cargo-util-schemas",
+ "clap",
+ "clap_complete",
+ "color-print",
+ "crates-io",
+ "curl",
+ "curl-sys",
+ "filetime",
+ "flate2",
+ "git2",
+ "git2-curl",
+ "gix",
+ "glob",
+ "hex",
+ "hmac",
+ "home",
+ "http-auth",
+ "humantime",
+ "ignore",
+ "im-rc",
+ "indexmap",
+ "itertools",
+ "jobserver",
+ "lazycell",
+ "libc",
+ "libgit2-sys",
+ "memchr",
+ "opener",
+ "os_info",
+ "pasetors",
+ "pathdiff",
+ "rand",
+ "regex",
+ "rusqlite",
+ "rustc-hash",
+ "rustc-stable-hash",
+ "rustfix",
+ "same-file",
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde_ignored",
+ "serde_json",
+ "sha1",
+ "shell-escape",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "tar",
+ "tempfile",
+ "thiserror 1.0.69",
+ "time",
+ "toml",
+ "toml_edit",
+ "tracing",
+ "tracing-chrome",
+ "tracing-subscriber",
+ "unicase",
+ "unicode-width 0.2.0",
+ "url",
+ "walkdir",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "cargo-credential"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a3e7c625670eacbefd48f552588c491eccc79a85a96898af13af7b312d1c4cd"
+dependencies = [
+ "anyhow",
+ "libc",
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+ "time",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "cargo-credential-libsecret"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "508a82e6202bdb857bed8fabd67a29cdb2e5c3dd3eeb283da3e225da5a5c700d"
+dependencies = [
+ "anyhow",
+ "cargo-credential",
+ "libloading",
+]
+
+[[package]]
+name = "cargo-credential-macos-keychain"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4635f2c8a02d08a16f8649672df1999f796c68bcd75784213a6495d8c190cddd"
+dependencies = [
+ "cargo-credential",
+ "security-framework",
+]
+
+[[package]]
+name = "cargo-credential-wincred"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a86ccaf9c6f49354e832c0eeb44b310ab953871fa2417d2e01ee3d153b310051"
+dependencies = [
+ "cargo-credential",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo-util"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc680c90073156fb5280c0c0127b779eef1f6292e41f7d6621acba3041e81c7d"
+dependencies = [
+ "anyhow",
+ "core-foundation",
+ "filetime",
+ "hex",
+ "ignore",
+ "jobserver",
+ "libc",
+ "miow",
+ "same-file",
+ "sha2",
+ "shell-escape",
+ "tempfile",
+ "tracing",
+ "walkdir",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "cargo-util-schemas"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a7801ec3ee336018f3f0e66680c3681e5eb58d283e1fad2809531dda7f1ed1"
+dependencies = [
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde-value",
+ "thiserror 1.0.69",
+ "toml",
+ "unicode-xid",
+ "url",
+]
+
+[[package]]
+name = "cc"
+version = "1.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
+dependencies = [
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+ "terminal_size",
+]
+
+[[package]]
+name = "clap_complete"
+version = "4.5.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01"
+dependencies = [
+ "clap",
+ "clap_lex",
+ "is_executable",
+ "shlex",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+
+[[package]]
+name = "clap_mangen"
+version = "0.2.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b4c3c54b30f0d9adcb47f25f61fcce35c4dd8916638c6b82fbd5f4fb4179e2"
+dependencies = [
+ "clap",
+ "roff",
+]
+
+[[package]]
+name = "clru"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59"
+
+[[package]]
+name = "color-print"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0"
+dependencies = [
+ "color-print-proc-macro",
+]
+
+[[package]]
+name = "color-print-proc-macro"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
+[[package]]
+name = "const-oid"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+[[package]]
+name = "constant_time_eq"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crates-io"
+version = "0.40.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f4884a8a380811c8ef088e7caeb68caeb665ffdb91f7276069e3c7828f168a"
+dependencies = [
+ "curl",
+ "percent-encoding",
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+ "url",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+
+[[package]]
+name = "crypto-bigint"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+dependencies = [
+ "generic-array",
+ "rand_core",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "ct-codecs"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df"
+
+[[package]]
+name = "curl"
+version = "0.4.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6"
+dependencies = [
+ "curl-sys",
+ "libc",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "socket2",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.4.78+curl-8.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf"
+dependencies = [
+ "cc",
+ "libc",
+ "libnghttp2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "dbus"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b"
+dependencies = [
+ "libc",
+ "libdbus-sys",
+ "winapi",
+]
+
+[[package]]
+name = "debcargo"
+version = "2.7.11"
+dependencies = [
+ "ansi_term",
+ "anyhow",
+ "cargo",
+ "cargo-util",
+ "cargo-util-schemas",
+ "chrono",
+ "clap",
+ "clap_mangen",
+ "env_logger",
+ "filetime",
+ "flate2",
+ "git2",
+ "glob",
+ "itertools",
+ "log",
+ "regex",
+ "semver",
+ "serde",
+ "serde_derive",
+ "tar",
+ "tempfile",
+ "textwrap",
+ "toml",
+ "walkdir",
+]
+
+[[package]]
+name = "der"
+version = "0.7.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
+dependencies = [
+ "const-oid",
+ "pem-rfc7468",
+ "zeroize",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+ "serde",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "dunce"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+
+[[package]]
+name = "ecdsa"
+version = "0.16.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
+dependencies = [
+ "der",
+ "digest",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+ "spki",
+]
+
+[[package]]
+name = "ed25519-compact"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "either"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.13.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "hkdf",
+ "pem-rfc7468",
+ "pkcs8",
+ "rand_core",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "env_filter"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "humantime",
+ "log",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "erased-serde"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d"
+dependencies = [
+ "serde",
+ "typeid",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
+[[package]]
+name = "faster-hex"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
+[[package]]
+name = "ff"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+dependencies = [
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
+[[package]]
+name = "filetime"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.4.1",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
+dependencies = [
+ "crc32fast",
+ "libz-sys",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+ "zeroize",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "git2"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
+dependencies = [
+ "bitflags 2.6.0",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "openssl-probe",
+ "openssl-sys",
+ "url",
+]
+
+[[package]]
+name = "git2-curl"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ff14527a1c242320039b138376f8e0786697a1b7b172bc44f6efda3ab9079f"
+dependencies = [
+ "curl",
+ "git2",
+ "log",
+ "url",
+]
+
+[[package]]
+name = "gix"
+version = "0.69.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d0eebdaecdcf405d5433a36f85e4f058cf4de48ee2604388be0dbccbaad353e"
+dependencies = [
+ "gix-actor",
+ "gix-attributes",
+ "gix-command",
+ "gix-commitgraph",
+ "gix-config",
+ "gix-credentials",
+ "gix-date",
+ "gix-diff",
+ "gix-dir",
+ "gix-discover",
+ "gix-features",
+ "gix-filter",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-ignore",
+ "gix-index",
+ "gix-lock",
+ "gix-negotiate",
+ "gix-object",
+ "gix-odb",
+ "gix-pack",
+ "gix-path",
+ "gix-pathspec",
+ "gix-prompt",
+ "gix-protocol",
+ "gix-ref",
+ "gix-refspec",
+ "gix-revision",
+ "gix-revwalk",
+ "gix-sec",
+ "gix-shallow",
+ "gix-submodule",
+ "gix-tempfile",
+ "gix-trace",
+ "gix-transport",
+ "gix-traverse",
+ "gix-url",
+ "gix-utils",
+ "gix-validate",
+ "gix-worktree",
+ "once_cell",
+ "prodash",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-actor"
+version = "0.33.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b24171f514cef7bb4dfb72a0b06dacf609b33ba8ad2489d4c4559a03b7afb3"
+dependencies = [
+ "bstr",
+ "gix-date",
+ "gix-utils",
+ "itoa",
+ "thiserror 2.0.11",
+ "winnow",
+]
+
+[[package]]
+name = "gix-attributes"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddf9bf852194c0edfe699a2d36422d2c1f28f73b7c6d446c3f0ccd3ba232cadc"
+dependencies = [
+ "bstr",
+ "gix-glob",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "kstring",
+ "smallvec",
+ "thiserror 2.0.11",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-bitmap"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d48b897b4bbc881aea994b4a5bbb340a04979d7be9089791304e04a9fbc66b53"
+dependencies = [
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-chunk"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6ffbeb3a5c0b8b84c3fe4133a6f8c82fa962f4caefe8d0762eced025d3eb4f7"
+dependencies = [
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-command"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb410b84d6575db45e62025a9118bdbf4d4b099ce7575a76161e898d9ca98df1"
+dependencies = [
+ "bstr",
+ "gix-path",
+ "gix-trace",
+ "shell-words",
+]
+
+[[package]]
+name = "gix-commitgraph"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8da6591a7868fb2b6dabddea6b09988b0b05e0213f938dbaa11a03dd7a48d85"
+dependencies = [
+ "bstr",
+ "gix-chunk",
+ "gix-features",
+ "gix-hash",
+ "memmap2",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-config"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6649b406ca1f99cb148959cf00468b231f07950f8ec438cc0903cda563606f19"
+dependencies = [
+ "bstr",
+ "gix-config-value",
+ "gix-features",
+ "gix-glob",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "memchr",
+ "once_cell",
+ "smallvec",
+ "thiserror 2.0.11",
+ "unicode-bom",
+ "winnow",
+]
+
+[[package]]
+name = "gix-config-value"
+version = "0.14.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11365144ef93082f3403471dbaa94cfe4b5e72743bdb9560719a251d439f4cee"
+dependencies = [
+ "bitflags 2.6.0",
+ "bstr",
+ "gix-path",
+ "libc",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-credentials"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82a50c56b785c29a151ab4ccf74a83fe4e21d2feda0d30549504b4baed353e0a"
+dependencies = [
+ "bstr",
+ "gix-command",
+ "gix-config-value",
+ "gix-path",
+ "gix-prompt",
+ "gix-sec",
+ "gix-trace",
+ "gix-url",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-date"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f"
+dependencies = [
+ "bstr",
+ "itoa",
+ "jiff",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-diff"
+version = "0.49.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8e92566eccbca205a0a0f96ffb0327c061e85bc5c95abbcddfe177498aa04f6"
+dependencies = [
+ "bstr",
+ "gix-hash",
+ "gix-object",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-dir"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fba2ffbcf4bd34438e8a8367ccbc94870549903d1f193a14f47eb6b0967e1293"
+dependencies = [
+ "bstr",
+ "gix-discover",
+ "gix-fs",
+ "gix-ignore",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-pathspec",
+ "gix-trace",
+ "gix-utils",
+ "gix-worktree",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-discover"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83bf6dfa4e266a4a9becb4d18fc801f92c3f7cc6c433dd86fdadbcf315ffb6ef"
+dependencies = [
+ "bstr",
+ "dunce",
+ "gix-fs",
+ "gix-hash",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-features"
+version = "0.39.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d85d673f2e022a340dba4713bed77ef2cf4cd737d2f3e0f159d45e0935fd81f"
+dependencies = [
+ "bytes",
+ "crc32fast",
+ "crossbeam-channel",
+ "flate2",
+ "gix-hash",
+ "gix-trace",
+ "gix-utils",
+ "libc",
+ "once_cell",
+ "parking_lot",
+ "prodash",
+ "sha1_smol",
+ "thiserror 2.0.11",
+ "walkdir",
+]
+
+[[package]]
+name = "gix-filter"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d0ecdee5667f840ba20c7fe56d63f8e1dc1e6b3bfd296151fe5ef07c874790a"
+dependencies = [
+ "bstr",
+ "encoding_rs",
+ "gix-attributes",
+ "gix-command",
+ "gix-hash",
+ "gix-object",
+ "gix-packetline-blocking",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "gix-utils",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-fs"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3d4fac505a621f97e5ce2c69fdc425742af00c0920363ca4074f0eb48b1db9"
+dependencies = [
+ "fastrand",
+ "gix-features",
+ "gix-utils",
+]
+
+[[package]]
+name = "gix-glob"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaf69a6bec0a3581567484bf99a4003afcaf6c469fd4214352517ea355cf3435"
+dependencies = [
+ "bitflags 2.6.0",
+ "bstr",
+ "gix-features",
+ "gix-path",
+]
+
+[[package]]
+name = "gix-hash"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b5eccc17194ed0e67d49285e4853307e4147e95407f91c1c3e4a13ba9f4e4ce"
+dependencies = [
+ "faster-hex",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-hashtable"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef65b256631078ef733bc5530c4e6b1c2e7d5c2830b75d4e9034ab3997d18fe"
+dependencies = [
+ "gix-hash",
+ "hashbrown 0.14.5",
+ "parking_lot",
+]
+
+[[package]]
+name = "gix-ignore"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6b1fb24d2a4af0aa7438e2771d60c14a80cf2c9bd55c29cf1712b841f05bb8a"
+dependencies = [
+ "bstr",
+ "gix-glob",
+ "gix-path",
+ "gix-trace",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-index"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "270645fd20556b64c8ffa1540d921b281e6994413a0ca068596f97e9367a257a"
+dependencies = [
+ "bitflags 2.6.0",
+ "bstr",
+ "filetime",
+ "fnv",
+ "gix-bitmap",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-traverse",
+ "gix-utils",
+ "gix-validate",
+ "hashbrown 0.14.5",
+ "itoa",
+ "libc",
+ "memmap2",
+ "rustix",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-lock"
+version = "15.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd3ab68a452db63d9f3ebdacb10f30dba1fa0d31ac64f4203d395ed1102d940"
+dependencies = [
+ "gix-tempfile",
+ "gix-utils",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-negotiate"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d27f830a16405386e9c83b9d5be8261fe32bbd6b3caf15bd1b284c6b2b7ef1a8"
+dependencies = [
+ "bitflags 2.6.0",
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-object",
+ "gix-revwalk",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-object"
+version = "0.46.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e42d58010183ef033f31088479b4eb92b44fe341b35b62d39eb8b185573d77ea"
+dependencies = [
+ "bstr",
+ "gix-actor",
+ "gix-date",
+ "gix-features",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-path",
+ "gix-utils",
+ "gix-validate",
+ "itoa",
+ "smallvec",
+ "thiserror 2.0.11",
+ "winnow",
+]
+
+[[package]]
+name = "gix-odb"
+version = "0.66.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb780eceb3372ee204469478de02eaa34f6ba98247df0186337e0333de97d0ae"
+dependencies = [
+ "arc-swap",
+ "gix-date",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-pack",
+ "gix-path",
+ "gix-quote",
+ "parking_lot",
+ "tempfile",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-pack"
+version = "0.56.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4158928929be29cae7ab97afc8e820a932071a7f39d8ba388eed2380c12c566c"
+dependencies = [
+ "clru",
+ "gix-chunk",
+ "gix-features",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "memmap2",
+ "parking_lot",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-packetline"
+version = "0.18.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "911aeea8b2dabeed2f775af9906152a1f0109787074daf9e64224e3892dde453"
+dependencies = [
+ "bstr",
+ "faster-hex",
+ "gix-trace",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-packetline-blocking"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce9004ce1bc00fd538b11c1ec8141a1558fb3af3d2b7ac1ac5c41881f9e42d2a"
+dependencies = [
+ "bstr",
+ "faster-hex",
+ "gix-trace",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-path"
+version = "0.10.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c40f12bb65a8299be0cfb90fe718e3be236b7a94b434877012980863a883a99f"
+dependencies = [
+ "bstr",
+ "gix-trace",
+ "home",
+ "once_cell",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-pathspec"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c472dfbe4a4e96fcf7efddcd4771c9037bb4fdea2faaabf2f4888210c75b81e"
+dependencies = [
+ "bitflags 2.6.0",
+ "bstr",
+ "gix-attributes",
+ "gix-config-value",
+ "gix-glob",
+ "gix-path",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-prompt"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79f2185958e1512b989a007509df8d61dca014aa759a22bee80cfa6c594c3b6d"
+dependencies = [
+ "gix-command",
+ "gix-config-value",
+ "parking_lot",
+ "rustix",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-protocol"
+version = "0.47.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c84642e8b6fed7035ce9cc449593019c55b0ec1af7a5dce1ab8a0636eaaeb067"
+dependencies = [
+ "bstr",
+ "gix-credentials",
+ "gix-date",
+ "gix-features",
+ "gix-hash",
+ "gix-lock",
+ "gix-negotiate",
+ "gix-object",
+ "gix-ref",
+ "gix-refspec",
+ "gix-revwalk",
+ "gix-shallow",
+ "gix-trace",
+ "gix-transport",
+ "gix-utils",
+ "maybe-async",
+ "thiserror 2.0.11",
+ "winnow",
+]
+
+[[package]]
+name = "gix-quote"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a1e282216ec2ab2816cd57e6ed88f8009e634aec47562883c05ac8a7009a63"
+dependencies = [
+ "bstr",
+ "gix-utils",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-ref"
+version = "0.49.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a91b61776c839d0f1b7114901179afb0947aa7f4d30793ca1c56d335dfef485f"
+dependencies = [
+ "gix-actor",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "gix-utils",
+ "gix-validate",
+ "memmap2",
+ "thiserror 2.0.11",
+ "winnow",
+]
+
+[[package]]
+name = "gix-refspec"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00c056bb747868c7eb0aeb352c9f9181ab8ca3d0a2550f16470803500c6c413d"
+dependencies = [
+ "bstr",
+ "gix-hash",
+ "gix-revision",
+ "gix-validate",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-revision"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61e1ddc474405a68d2ce8485705dd72fe6ce959f2f5fe718601ead5da2c8f9e7"
+dependencies = [
+ "bstr",
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-object",
+ "gix-revwalk",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-revwalk"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "510026fc32f456f8f067d8f37c34088b97a36b2229d88a6a5023ef179fcb109d"
+dependencies = [
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-sec"
+version = "0.10.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8b876ef997a955397809a2ec398d6a45b7a55b4918f2446344330f778d14fd6"
+dependencies = [
+ "bitflags 2.6.0",
+ "gix-path",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "gix-shallow"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d2673242e87492cb6ff671f0c01f689061ca306c4020f137197f3abc84ce01"
+dependencies = [
+ "bstr",
+ "gix-hash",
+ "gix-lock",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-submodule"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2455f8c0fcb6ebe2a6e83c8f522d30615d763eb2ef7a23c7d929f9476e89f5c"
+dependencies = [
+ "bstr",
+ "gix-config",
+ "gix-path",
+ "gix-pathspec",
+ "gix-refspec",
+ "gix-url",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-tempfile"
+version = "15.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2feb86ef094cc77a4a9a5afbfe5de626897351bbbd0de3cb9314baf3049adb82"
+dependencies = [
+ "gix-fs",
+ "libc",
+ "once_cell",
+ "parking_lot",
+ "tempfile",
+]
+
+[[package]]
+name = "gix-trace"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7"
+
+[[package]]
+name = "gix-transport"
+version = "0.44.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd04d91e507a8713cfa2318d5a85d75b36e53a40379cc7eb7634ce400ecacbaf"
+dependencies = [
+ "base64",
+ "bstr",
+ "curl",
+ "gix-command",
+ "gix-credentials",
+ "gix-features",
+ "gix-packetline",
+ "gix-quote",
+ "gix-sec",
+ "gix-url",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-traverse"
+version = "0.43.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed47d648619e23e93f971d2bba0d10c1100e54ef95d2981d609907a8cabac89"
+dependencies = [
+ "bitflags 2.6.0",
+ "gix-commitgraph",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-revwalk",
+ "smallvec",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-url"
+version = "0.28.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d096fb733ba6bd3f5403dba8bd72bdd8809fe2b347b57844040b8f49c93492d9"
+dependencies = [
+ "bstr",
+ "gix-features",
+ "gix-path",
+ "percent-encoding",
+ "thiserror 2.0.11",
+ "url",
+]
+
+[[package]]
+name = "gix-utils"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba427e3e9599508ed98a6ddf8ed05493db114564e338e41f6a996d2e4790335f"
+dependencies = [
+ "bstr",
+ "fastrand",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "gix-validate"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd520d09f9f585b34b32aba1d0b36ada89ab7fefb54a8ca3fe37fc482a750937"
+dependencies = [
+ "bstr",
+ "thiserror 2.0.11",
+]
+
+[[package]]
+name = "gix-worktree"
+version = "0.38.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "756dbbe15188fa22540d5eab941f8f9cf511a5364d5aec34c88083c09f4bea13"
+dependencies = [
+ "bstr",
+ "gix-attributes",
+ "gix-features",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-ignore",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "gix-validate",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "globset"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+dependencies = [
+ "ahash",
+ "allocator-api2",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
+
+[[package]]
+name = "hashlink"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
+dependencies = [
+ "hashbrown 0.14.5",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "home"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "http-auth"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "643c9bbf6a4ea8a656d6b4cd53d34f79e3f841ad5203c1a55fb7d761923bc255"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "ignore"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1"
+dependencies = [
+ "crossbeam-deque",
+ "globset",
+ "log",
+ "memchr",
+ "regex-automata 0.4.9",
+ "same-file",
+ "walkdir",
+ "winapi-util",
+]
+
+[[package]]
+name = "im-rc"
+version = "15.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
+dependencies = [
+ "bitmaps",
+ "rand_core",
+ "rand_xoshiro",
+ "sized-chunks",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.15.1",
+]
+
+[[package]]
+name = "is_executable"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "jiff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb"
+dependencies = [
+ "jiff-tzdb-platform",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "jiff-tzdb"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653"
+
+[[package]]
+name = "jiff-tzdb-platform"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329"
+dependencies = [
+ "jiff-tzdb",
+]
+
+[[package]]
+name = "jobserver"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "kstring"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
+dependencies = [
+ "static_assertions",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.155"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+
+[[package]]
+name = "libdbus-sys"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
+name = "libgit2-sys"
+version = "0.17.0+1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224"
+dependencies = [
+ "cc",
+ "libc",
+ "libssh2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libloading"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
+dependencies = [
+ "cfg-if",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "libnghttp2-sys"
+version = "0.1.10+1.61.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "959c25552127d2e1fa72f0e52548ec04fc386e827ba71a7bd01db46a447dc135"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "libsqlite3-sys"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
+dependencies = [
+ "cc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
+
+[[package]]
+name = "maybe-async"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "memmap2"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "miow"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "normpath"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "opener"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681"
+dependencies = [
+ "bstr",
+ "dbus",
+ "normpath",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "ordered-float"
+version = "2.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "orion"
+version = "0.17.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abdb10181903c8c4b016ba45d6d6d5af1a1e2a461aa4763a83b87f5df4695e5"
+dependencies = [
+ "fiat-crypto",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "os_info"
+version = "3.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092"
+dependencies = [
+ "log",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "p384"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "primeorder",
+ "sha2",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.5.1",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "pasetors"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b719f62f9b77cfadf01500984ab26c7bda71b3f1e497e9dbb055ff466dbe2a86"
+dependencies = [
+ "ct-codecs",
+ "ed25519-compact",
+ "getrandom",
+ "orion",
+ "p384",
+ "rand_core",
+ "regex",
+ "serde",
+ "serde_json",
+ "sha2",
+ "subtle",
+ "time",
+ "zeroize",
+]
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+dependencies = [
+ "base64ct",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+
+[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "primeorder"
+version = "0.13.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+dependencies = [
+ "elliptic-curve",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "prodash"
+version = "29.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a266d8d6020c61a437be704c5e618037588e1985c7dbb7bf8d265db84cffe325"
+dependencies = [
+ "log",
+ "parking_lot",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_xoshiro"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
+dependencies = [
+ "bitflags 2.6.0",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rfc6979"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+dependencies = [
+ "hmac",
+ "subtle",
+]
+
+[[package]]
+name = "roff"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3"
+
+[[package]]
+name = "rusqlite"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e"
+dependencies = [
+ "bitflags 2.6.0",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
+ "libsqlite3-sys",
+ "smallvec",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
+
+[[package]]
+name = "rustc-stable-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2febf9acc5ee5e99d1ad0afcdbccc02d87aa3f857a1f01f825b80eacf8edfcd1"
+
+[[package]]
+name = "rustfix"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f66156d7471ff4f12253cd7fd76dfe637a595a9418168154e8570f3947fe9a8"
+dependencies = [
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+ "tracing",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags 2.6.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "sec1"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
+dependencies = [
+ "bitflags 2.6.0",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.214"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-untagged"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6"
+dependencies = [
+ "erased-serde",
+ "serde",
+ "typeid",
+]
+
+[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.214"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_ignored"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8e319a36d1b52126a0d608f24e93b2d81297091818cd70625fcf50a15d84ddf"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.132"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha1_smol"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "shell-escape"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+
+[[package]]
+name = "shell-words"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signature"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+dependencies = [
+ "digest",
+ "rand_core",
+]
+
+[[package]]
+name = "sized-chunks"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
+dependencies = [
+ "bitmaps",
+ "typenum",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "smawk"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
+
+[[package]]
+name = "socket2"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "spki"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "subtle"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
+[[package]]
+name = "supports-hyperlinks"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee"
+
+[[package]]
+name = "supports-unicode"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
+
+[[package]]
+name = "syn"
+version = "2.0.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tar"
+version = "0.4.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
+dependencies = [
+ "rustix",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width 0.1.14",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+dependencies = [
+ "thiserror-impl 2.0.11",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "time"
+version = "0.3.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+
+[[package]]
+name = "time-macros"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "toml"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-chrome"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724"
+dependencies = [
+ "serde_json",
+ "tracing-core",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
+name = "typeid"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf"
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicase"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-bom"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "unicode-width"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "url"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "winnow"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "xattr"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
+dependencies = [
+ "libc",
+ "linux-raw-sys",
+ "rustix",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..f8d96ab
--- /dev/null
@@ -0,0 +1,129 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.58"
+name = "debcargo"
+version = "2.7.11"
+authors = [
+    "Josh Triplett <josh@joshtriplett.org>",
+    "Ximin Luo <infinity0@debian.org>",
+    "Vasudev Kamath <vasudev@copyninja.info>",
+    "Fabian Grünbichler <debian@fabian.gruenbichler.email>",
+]
+build = false
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "Create a Debian package from a Cargo crate."
+readme = "README.md"
+license = "MIT/Apache-2.0"
+repository = "https://salsa.debian.org/rust-team/debcargo"
+
+[lib]
+name = "debcargo"
+path = "src/lib.rs"
+
+[[bin]]
+name = "debcargo"
+path = "src/bin/debcargo.rs"
+
+[[test]]
+name = "config_tests"
+path = "tests/config_tests.rs"
+
+[[test]]
+name = "local-crate"
+path = "tests/local-crate.rs"
+
+[[test]]
+name = "manpages"
+path = "tests/manpages.rs"
+
+[dependencies.ansi_term]
+version = "0.12"
+
+[dependencies.anyhow]
+version = "1.0"
+
+[dependencies.cargo]
+version = "0.86"
+
+[dependencies.cargo-util]
+version = "0.2.14"
+
+[dependencies.cargo-util-schemas]
+version = "0.7"
+
+[dependencies.chrono]
+version = "0.4.31"
+
+[dependencies.clap]
+version = "4.5"
+features = [
+    "cargo",
+    "derive",
+    "wrap_help",
+]
+
+[dependencies.clap_mangen]
+version = "0.2.29"
+
+[dependencies.env_logger]
+version = "0.11"
+
+[dependencies.filetime]
+version = "0.2"
+
+[dependencies.flate2]
+version = "1"
+
+[dependencies.git2]
+version = ">= 0.19, < 0.21"
+
+[dependencies.glob]
+version = "0.3"
+
+[dependencies.itertools]
+version = "0.13"
+
+[dependencies.log]
+version = "0.4"
+
+[dependencies.regex]
+version = "1.0"
+
+[dependencies.semver]
+version = "1"
+
+[dependencies.serde]
+version = "1"
+
+[dependencies.serde_derive]
+version = "1"
+
+[dependencies.tar]
+version = "0.4"
+
+[dependencies.tempfile]
+version = "3"
+
+[dependencies.textwrap]
+version = "0.16"
+
+[dependencies.toml]
+version = "0.8"
+
+[dependencies.walkdir]
+version = "2"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644 (file)
index 0000000..a1545b8
--- /dev/null
@@ -0,0 +1,40 @@
+[package]
+name = "debcargo"
+version = "2.7.11"
+authors = [
+ "Josh Triplett <josh@joshtriplett.org>",
+ "Ximin Luo <infinity0@debian.org>",
+ "Vasudev Kamath <vasudev@copyninja.info>",
+ "Fabian Grünbichler <debian@fabian.gruenbichler.email>",
+]
+license = "MIT/Apache-2.0"
+repository = "https://salsa.debian.org/rust-team/debcargo"
+description = "Create a Debian package from a Cargo crate."
+edition = "2021"
+rust-version = "1.58"
+
+[dependencies]
+ansi_term = "0.12"
+anyhow = "1.0"
+cargo = "0.86"
+cargo-util = "0.2.14"
+cargo-util-schemas = "0.7"
+clap = { version = "4.5", features = ["cargo", "derive", "wrap_help"] }
+clap_mangen = { version = "0.2.29" }
+chrono = "0.4.31"
+env_logger = "0.11"
+filetime = "0.2"
+flate2 = "1"
+git2 = ">= 0.19, < 0.21"
+glob = "0.3"
+itertools = "0.13"
+log = "0.4"
+regex = "1.0"
+semver = "1"
+serde = "1"
+serde_derive = "1"
+tar = "0.4"
+textwrap = "0.16"
+tempfile = "3"
+toml = "0.8"
+walkdir = "2"
diff --git a/HACKING.md b/HACKING.md
new file mode 100644 (file)
index 0000000..10ab86d
--- /dev/null
@@ -0,0 +1,89 @@
+This file contains information about developing debcargo itself.
+
+
+## Dependencies
+
+For testing:
+
+```shell
+# Install dependencies for building (see README.md), then:
+$ apt-get install dh-cargo lintian
+```
+
+For development:
+
+```shell
+# As above, then:
+$ cargo install cargo-outdated
+$ cargo outdated -R
+```
+
+
+## Testing
+
+Whenever you make a major change, you should run:
+
+```shell
+$ tests/sh/integrate.sh -kbr debcargo exa fd-find ripgrep
+```
+
+in order to test it over a few hundred crates. Fix any build errors and
+important lintian errors that crop up.
+
+If you make a change that has wide-reaching implications, such as messing with
+the dependency logic, do a more thorough test:
+
+```shell
+$ tests/sh/integrate.sh -kbR debcargo exa fd-find ripgrep mdbook sccache
+```
+
+This will run the test over around a thousand crates. -R runs it over all the
+transitive dependencies of all the binary packages, which is needed for entry
+into Debian Testing. This is wider than -r, which runs the test over all the
+transitive build-dependencies of the source package, which is needed for entry
+into Debian Unstable.
+
+### Details
+
+To test the `debcargo` produced packages, you can run the following script.
+
+```shell
+$ tests/sh/integrate.sh crate[s]
+```
+
+where you can provide a list of crate names or local directories containing
+crates, and the script will run debcargo to create a source package (`.dsc`)
+and run lintian over it. If you find any issues, please add to the bugs in
+TODO.md file.
+
+```shell
+$ tests/sh/integrate.sh -kb crate[s]
+```
+
+will additionally run [sbuild](https://wiki.debian.org/sbuild) on the source
+package to build binary Debian packages (`.deb`) and run lintian over that too.
+It will automatically pick up any extra .debs you already have in the output
+directory, if they are dependencies of what you're building. The `-k` flag
+tells the script not to wipe the directory before it does anything else.
+
+```shell
+$ tests/sh/integrate.sh -kbr crate[s]
+```
+
+will run the script recursively over the listed crate(s) and all the transitive
+build-dependencies of the generated source packages, in dependency order. This
+covers all the dependencies that are needed for entry into Debian Unstable, and
+typically covers a few hundred crates. You may want or need to edit or update
+some of the overrides in `tests/configs`, to prune old or buggy dependencies.
+
+```shell
+$ tests/sh/integrate.sh -kbR crate[s]
+```
+
+will run the script recursively over the listed crate(s) and all the transitive
+runtime-dependencies of the binary packages, in dependency order. This covers
+all the dependencies that are needed for entry into Debian Testing, and
+typically covers a few thousand crates. You may want or need to edit or update
+some of the overrides in `tests/configs`, to prune old or buggy dependencies.
+
+See `-h` for other options.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..6c197de
--- /dev/null
+++ b/README.md
@@ -0,0 +1,110 @@
+Rust crates to Debian packages
+==============================
+
+`debcargo` is the official tool for packaging Rust crates to be part of the
+[Debian](https://www.debian.org/) system.
+
+It creates a Debian source package (`*.dsc`) from a Rust crate that follows
+Debian's [general packaging policy](https://www.debian.org/doc/debian-policy/)
+as well as the Debian Rust team's [crate packaging
+policy](https://wiki.debian.org/Teams/RustPackaging/Policy).
+
+
+## Features ##
+
+ * Easy to customize, using config files and overlay directories. This includes
+   patching or otherwise fixing Rust crates to adhere to Debian policy.
+ * Guess copyright information from crate metadata and source code, used to
+   suggest appropriate values for `debian/copyright`.
+ * Put `FIXME (hint)` strings where it can't detect full information, so user
+   can provide an override/overlay or manually fix it.
+ * Resulting packages automatically support general functionality available to
+   all policy-conforming Debian packages, such as:
+   * binaries for [10+ architectures](https://www.debian.org/ports/) are made
+     available directly to users, via `apt-get`
+   * debugging symbols are placed in a separate binary package, integrating
+     with the standard Debian [distribution system for debugging
+     symbols](https://wiki.debian.org/HowToGetABacktrace)
+   * full system integration with non-Rust software, including cross-language
+     dependency resolution
+   * cross-compilation support, including automatic resolution and installation
+     of non-Rust cross-dependencies, via Debian build tools such as `sbuild`.
+ * Determine a crate's full dependency tree (i.e. build order), from both
+   Debian packaging and QA perspectives.
+
+
+## Installation
+
+On Debian systems, `debcargo` can be installed the usual way:
+
+```shell
+$ apt-get install debcargo
+```
+
+To build locally for development:
+
+```shell
+$ apt-get build-dep debcargo
+$ cargo build debcargo
+```
+
+On non-Debian systems, you can try simply:
+
+```shell
+$ cargo build debcargo
+```
+
+and fix any build errors that come up, e.g. by installing missing libraries.
+Probably, this will include OpenSSL as a dependency of cargo.
+
+
+## Examples ##
+
+To download and unpack the latest `clap` crate and prepare the source package:
+
+```shell
+$ debcargo package clap
+```
+
+To download and unpack version `2.25.0` of `clap` crate and prepare the source package:
+
+```shell
+$ debcargo package clap =2.25.0
+```
+
+To provide additional packaging-specific config for downloading and packaging
+latest `clap` crate from crates.io:
+
+```shell
+$ debcargo package --config clap-2/debian/debcargo.toml clap
+```
+
+See `debcargo.toml.example` for a sample TOML file.
+
+
+## Long-term package maintenance
+
+The Debian Rust team uses this tool together with the configs and overlays in
+https://salsa.debian.org/rust-team/debcargo-conf/. If you are interested in
+contributing, please see that repository for further information and
+instructions on how to collaborate with us.
+
+
+## Building unofficial Debian packages
+
+Debian packaging policy is quite detailed. If you just want to create Debian
+binary packages (`*.deb`) without worrying about these policies, you may want
+to use other tools instead that ignore and bypass these policies. For example,
+`cargo-deb`.
+
+The trade-off is that the resulting packages integrate less well with a Debian
+system, and do not integrate at all with the Debian build system, which means
+you lose the features described earlier. Furthermore, you will be responsible
+for hosting and distributing those packages yourself, outside of the official
+Debian distribution infrastructure.
+
+
+## License ##
+
+Debcargo is licensed under `MIT/Apache-2.0`. It is written by `Josh Triplett`
+and `Ximin Luo`, and improved by members of **Debian Rust Maintainers team**
diff --git a/TODO.md b/TODO.md
new file mode 100644 (file)
index 0000000..3d9e017
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,26 @@
+See https://salsa.debian.org/groups/rust-team/-/issues
+
+See HACKING.md for development and testing instructions.
+
+## Lower-priority tasks
+
+Minor issues
+
+- fs::rename cannot handle cross-device moves, e.g. if --directory is on a
+  different partition from . then debcargo fails
+
+- the ? syntax loses the stack, use Result.expect() to give context, or use
+  error-chain instead...
+
+- [ ] globset, ignore, termcolor:
+      When generating d/copyright, failed to clone repository
+      https://github.com/BurntSushi/ripgrep/tree/master/XXX: unexpected HTTP status code: 404; class=Net (12)
+
+Features for later
+
+- [ ] Integrate `apt-pkg-native` crate to check if the crate or its dependency
+      is already in archive and display information.
+- [ ] Display first level dependency with equivalent Debian names at the end
+      which are not yet packaged in Debian as a information to maintainer.
+- [ ] Employ `licensecheck` tool to look for license and copyright information.
+      Currently we use regex to grep through sources.
diff --git a/debcargo.toml.example b/debcargo.toml.example
new file mode 100644 (file)
index 0000000..bbd7e8d
--- /dev/null
@@ -0,0 +1,277 @@
+# Whether to generate a package for the binary crate. If omitted, defaults to
+# true unless semver_suffix (see below) is also true.
+#bin = true
+
+# Name for the binary crate. Defaults to "<default>" which means the crate
+# name, with no "rust-" prefix and with underscores replaced by hyphens.
+#bin_name = "<default>"
+
+# Add the semver to the package name, to allow co-installation with other
+# versions of the same crate. This should only be true for crates older than
+# the most up-to-date version in Debian, and only if they are needed as a
+# (direct or indirect) build dependency of another binary crate.
+#
+# If you set this to true, you should either omit "bin" or set it to false,
+# unless you are sure the old and new packages are co-installable.
+#semver_suffix = false
+
+# Overlay directory to copy on top of the generated one, given relative to the
+# directory that contains this config file. If any files conflict with the ones
+# generated by debcargo, the latter are moved to <file>.debcargo.hint instead.
+#
+# For the special case of debian/changelog, generated entries will be prepended
+# to the top of the existing d/changelog (from the overlay), rather than stored
+# in debian/changelog.debcargo.hint. A further exception: if the distribution
+# of the top entry in the existing d/changelog is
+# UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO then that whole entry will be
+# *replaced* with the generated entry, not prepended.
+#
+# Normally, any "hints" generated are written back to the overlay directory,
+# overwriting any hints that may have previously been stored there. For the
+# special case of debian/changelog, that is written-back as-is. Therefore, it
+# is strongly recommended that you keep the overlay directory tracked in
+# version control. To disable this behaviour, give --no-overlay-write-back on
+# the debcargo command line.
+#
+#overlay = "."
+
+# Local directory where crate can be found, instead of crates.io. Resolved
+# relative to the directory that contains this config file. Note: this is
+# currently experimental and only works for crates whose dependencies are all
+# published on crates.io. For example, not rustup. This limitation will
+# hopefully be fixed in the future.
+#
+#crate_src_path = "../.."
+
+# Paths from the crate tarball, to exclude from the orig tarball.
+# See https://docs.rs/glob/latest/glob/struct.Pattern.html for syntax
+#excludes = ["libgit2/**"]
+
+# Paths from the crate tarball, that have been manually reviewed to adhere to
+# Debian policy. debcargo has a crude method for detecting files that might not
+# fit within policy, and will give a fatal error if any are detected. In the
+# exceptional cases where the method gives a false-positive, add them here.
+#whitelist = ["libgit2/**"]
+
+# Whether to allow prerelease deps, by rewriting these to the released version.
+# This should only be enabled for certain crates if really necessary, and first
+# you should check that they can actually build when this is enabled.
+#allow_prerelease_deps = false
+
+# This is the stem of the short description for each binary package. By default
+# `debcargo` will try to auto-extract a description from `Cargo.toml` but
+# sometimes this may lead to a meaningless, weird short description.
+#
+# The full short description of each binary package is constructed using this
+# string plus an auto-generated suffix. The full string can be overridden by
+# the [packages.KEY].summary config key, see below.
+#summary = "PLACEHOLDER"
+
+# This is the stem of the long description for each binary package. By default
+# this is empty.
+#
+# The full long description of each binary package is constructed using this
+# string plus an auto-generated suffix. The full string can be overridden by
+# the [packages.KEY].description config key, see below.
+#description = """
+#PLACEHOLDER
+#"""
+
+# Maintainer
+#
+# Defaults to pkg-rust-team, should only be overriden with care. If overridden,
+# vcs_* in [source] should also be overridden, otherwise they point the Rust
+# Team's salsa project.
+#
+#maintainer = "PLACEHOLDER"
+
+# Uploaders. This affects the Uploaders: field in debian/control as well as the
+# additional maintainers listed in debian/copyright. The naming is historical;
+# in Debian today for team-maintained packages, this is generally taken to mean
+# "the main individuals" responsible for the package - anyone on the team is
+# "morally allowed" to perform the upload as long as they specify "Team upload"
+# in debian/changelog; this is done automatically by debcargo.
+uploaders = [ "foo bar <foo@debian.org>" ]
+
+# This is a temporary work-around in order to address situations where certain
+# Debian infrastructure people claim (without supplying concrete evidence) that
+# rust crate metadata is "too large". This flag addresses this, effectively by
+# forcing all crate features together into a single feature. This increases the
+# dependency footprint of the generated packages and therefore should not be
+# enabled unless absolutely necessary. It can also cause cyclic dependencies in
+# some cases, and in these cases it simply cannot be enabled, as packages in
+# the cycle become uninstallable. Most crates should not need this, and you
+# should not enable this just because "somebody told you so".
+#collapse_features = false
+
+# Set the Rules-Requires-Root field in debian/control; by default, this unset.
+#requires_root = "yes"
+
+[source]
+
+# Debian Standards-Version to use. By default debcargo uses latest policy version.
+#policy = "4.0.0"
+
+# Override or provide missing homepage for crate
+#homepage = "https://clap.rs"
+
+# Override the VCS entries.
+# By default this points to a relevant subdirectory underneath the main
+# repository for debcargo config files, owned by the Debian Rust Maintainers:
+# https://salsa.debian.org/rust-team/debcargo-conf/
+# Please only override this if your package is truly special, e.g. it combines
+# lots of languages and/or there is not a crate at the top-level directory. In
+# most cases you should prefer packaging as part of the Debian Rust Team, see
+# https://wiki.debian.org/Teams/RustPackaging/Policy
+#
+#vcs_git = "https://salsa.debian.org/special_package/rust-special-0.1.git"
+#vcs_browser = "https://salsa.debian.org/special_package/rust-special-0.1"
+
+# Section override for the source package. Unless overridden here, library
+# crates get "rust" and non-library crates get a "FIXME".
+#section = "rust"
+
+# Extra Build-Depends on top of those generated by debcargo.
+# If you defined a custom d/rules that does extra stuff on top of dh-cargo,
+# then you may need to use this.
+#
+# OTOH, if your crate needs external development headers to build, these should
+# probably instead go in the [packages.lib] depends key rather than this key.
+# debcargo will then automatically add those into the package Build-Depends if
+# needed by dh-cargo; you don't have to add them here as well. Unless the extra
+# dependency is needed for the clean target of debian/rules, the _indep variant
+# is probably the right choice.
+#build_depends = ["PLACEHOLDER", "PLACEHOLDER"]
+#build_depends_arch = ["PLACEHOLDER", "PLACEHOLDER"]
+#build_depends_indep = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# If set to `true`, do not add <!nocheck> annotations to build dependencies.
+# This should only be needed if your librust-* packages actually require some
+# build step, or your package does something else custom.
+#skip_nocheck = false
+
+# Build-Depends to subtract from those generated by debcargo. This should be
+# used when our default generated Build-Depends results in a cycle. For
+# example, this might happen if:
+#
+# - crate A's default-feature depends on crate B's no-default-features (which has no dependencies)
+# - crate B's default-feature depends on crate A's no-default-features (which has no dependencies)
+#
+# In these cases, you'll need to (for example) add "librustA+B-dev <!nocheck>"
+# to build_depends_excludes in A's debcargo.toml to break the cycle, and also
+# add override_dh_auto_test to A's d/rules to avoid selecting the B feature
+# when running the test build. Depending on the exact situation, it should be
+# sufficient to do this override only for one of the packages in the cycle.
+#
+# Note that binary package Depends must be left alone in order to correctly
+# express the dependencies; these ought not to have cycles in anyway, even in
+# a case like the above example.
+#
+# This field should *not* be used to exclude arch-specific dependencies. We
+# want to include them to support cross-compiling, and they should cause no
+# problems since they are just source code. If our test "cargo build" fails for
+# one of those dependencies, it should be handled in that package by disabling
+# the failing test on the architectures that they are expected to fail on. This
+# field applies to all three categories of build dependencies (Build-Depends,
+# Build-Depends-Arch and Build-Depends-Indep)
+#build_depends_excludes = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# Binary package overrides.
+#
+# Different values for KEY selects different binary packages:
+# lib           - the package for the library crate
+# "lib+FEATURE" - the metapackage for feature FEATURE
+# bin           - the package for the binary crate
+#
+[packages.KEY]
+
+# Section override for the binary package. Use this if your crate is both a
+# library and a binary crate; in this case, omit source.section which will
+# default to "rust" and override this value for your binary package.
+#section = "PLACEHOLDER"
+
+# Short description for the package. If omitted, debcargo autogenerates this
+# using the top-level "summary" key plus a suffix describing the feature.
+#summary = "PLACEHOLDER"
+
+# Long description for the package. If omitted, debcargo autogenerates this
+# using the top-level "description" key plus a suffix describing the feature.
+#description = """
+#PLACEHOLDER
+#"""
+
+# Value for the Architecture field of the package. If omitted, debcargo will
+# set "any" for both 'bin' and 'lib' packages.
+# Note that 'lib' packages should not be "Architecture: all". For reference,
+# see https://rust-team.pages.debian.net/book/policy.html#why-architecture-any
+#architecture = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# Value for the Multi-Arch field of the package. If omitted, debcargo will
+# automatically set 'foreign' for 'bin', and 'same' for all 'lib' packages.
+#multi_arch = "no|same|foreign|allowed"
+
+# Additional Depends on top of the ones generated by debcargo. This should be
+# used to pull in system libraries for crates that need them to build. You'll
+# want the -dev versions of the library packages, since our crate packages are
+# development packages and not runtime packages. These will be automatically
+# added to the source packages `Build-Depends-Arch` field as well.
+#depends = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# We generate an autopkgtest (post-install test) for every feature, and also
+# run `cargo test` for the default feature set during build-time if there are
+# no additional dev-dependencies.
+#
+# However sometimes this may not work, e.g. if the crate is part of a larger
+# workspace and its tests require files from the workspace directory. Or if
+# the crate author is simply negligent and didn't ensure the test passes for
+# all features. In these cases, you can use this setting to mark the test as
+# "flaky" to ignore failures. Special cases for packages.KEY:
+#
+# packages."lib+@"      - disables the test for the --all-features autopkgtest
+#
+# The effect is transitive to its reverse-dependencies, so e.g. if you specify
+# this for feature A, and feature B depends on feature A, then feature B also
+# implicitly has this set. To unset it on feature B (and its transitive rdeps),
+# explicit set this to false for feature B as well.
+#
+# So for example if the test breaks for the bare library (when running with
+# --no-default-features) but works when the std feature is enabled, set this to
+# true for [packages.lib] and false for [packages."lib+std"].
+#
+# Note: debcargo will error if you set these in an inconsistent way. For
+# example if feature A depends on {B, C}, B says true and C says false, of
+# course we cannot determine what A should be. You can suppress the error by
+# explicitly giving A a value, either true or false.
+#
+#test_is_broken = false
+
+# Some tests depend on extra system tools or libraries, which need to be given
+# to autopkgtest. Like test_is_broken, the effect is transitive to its rdeps.
+#test_depends = []
+
+# Some tests might be broken on certain architectures, or just take too long.
+# This allows to (transitively) set Architecture restrictions (either positive
+# or negative) for autopkgtests. Use an explicit empty list ([]) to reset an
+# inherited restriction. The "@" (all features) test will default to a
+# combination of all individual restrictions.
+#test_architecture = []
+
+# Note: we do not (currently) support unsetting of this in indirect rdeps. This
+# would result in similar conflict issues as documented for test_is_broken. It
+# is possible to work around it similarly, by requiring manual resolution - but
+# cancelling dependencies is harder to implement than true/false so we avoid it
+# for now. Please file an issue if you have a real use-case for it.
+
+# More additional fields. This is mostly useful for binary packages that might
+# relate to other external programs, e.g. debcargo Recommends cargo.
+# The values here will extend those set by debcargo automatically.
+#recommends = ["PLACEHOLDER", "PLACEHOLDER"]
+#suggests = ["PLACEHOLDER", "PLACEHOLDER"]
+#provides = ["PLACEHOLDER", "PLACEHOLDER"]
+#breaks = ["PLACEHOLDER", "PLACEHOLDER"]
+#replaces = ["PLACEHOLDER", "PLACEHOLDER"]
+#conflicts = ["PLACEHOLDER", "PLACEHOLDER"]
+
+# Extra lines to include in the stanza, freeform. Use this to include things
+# that debcargo doesn't handle, such as Breaks, Conflicts, Replaces.
+#extra_lines = ["PLACEHOLDER", "PLACEHOLDER"]
diff --git a/manpages/debcargo-build-order.1 b/manpages/debcargo-build-order.1
new file mode 100644 (file)
index 0000000..7f9a4e7
--- /dev/null
@@ -0,0 +1,32 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-build-order 1  "build-order " 
+.SH NAME
+debcargo\-build\-order \- Print the transitive dependencies of a package in topological order
+.SH SYNOPSIS
+\fBdebcargo build\-order\fR [\fB\-\-config\-dir\fR] [\fB\-\-resolve\-type\fR] [\fB\-\-emulate\-collapse\-features\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Print the transitive dependencies of a package in topological order
+.SH OPTIONS
+.TP
+\fB\-\-config\-dir\fR \fI<CONFIG_DIR>\fR
+Directory for configs. The config subdirectory for a given crate is looked up by their crate name and version, from more specific to less specific, e.g. <crate>\-1.2.3, then <crate>\-1.2, then <crate>\-1 and finally <crate>. The config file is read from the debian/debcargo.toml subpath of the looked\-up subdirectory
+.TP
+\fB\-\-resolve\-type\fR \fI<RESOLVE_TYPE>\fR [default: SourceForDebianUnstable]
+Resolution type
+.br
+
+.br
+[\fIpossible values: \fRSourceForDebianUnstable, BinaryAllForDebianTesting]
+.TP
+\fB\-\-emulate\-collapse\-features\fR
+Emulate resolution as if every package were built with \-\-collapse\-features
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators
diff --git a/manpages/debcargo-deb-dependencies.1 b/manpages/debcargo-deb-dependencies.1
new file mode 100644 (file)
index 0000000..4e3dc59
--- /dev/null
@@ -0,0 +1,28 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-deb-dependencies 1  "deb-dependencies " 
+.SH NAME
+debcargo\-deb\-dependencies \- Print the dependencies of a package in d/control format
+.SH SYNOPSIS
+\fBdebcargo deb\-dependencies\fR [\fB\-\-features\fR] [\fB\-\-all\-features\fR] [\fB\-\-no\-default\-features\fR] [\fB\-\-allow\-prerelease\-deps\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICARGO_TOML\fR> 
+.SH DESCRIPTION
+Print the dependencies of a package in d/control format
+.SH OPTIONS
+.TP
+\fB\-\-features\fR \fI<FEATURES>\fR
+Features to include in dependencies
+.TP
+\fB\-\-all\-features\fR
+Include all features in dependencies
+.TP
+\fB\-\-no\-default\-features\fR
+Do not include default feature in dependencies
+.TP
+\fB\-\-allow\-prerelease\-deps\fR
+Allow prerelease versions of dependencies
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICARGO_TOML\fR>
+Cargo.toml for generating dependencies
diff --git a/manpages/debcargo-deb-src-name.1 b/manpages/debcargo-deb-src-name.1
new file mode 100644 (file)
index 0000000..a0e9a95
--- /dev/null
@@ -0,0 +1,19 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-deb-src-name 1  "deb-src-name " 
+.SH NAME
+debcargo\-deb\-src\-name \- Print the Debian package name for a crate
+.SH SYNOPSIS
+\fBdebcargo deb\-src\-name\fR [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Print the Debian package name for a crate
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators. If empty string, resolves to the latest version. If given here, i.e. not omitted then print the package name as if the config option semver_suffix was set to true
diff --git a/manpages/debcargo-extract.1 b/manpages/debcargo-extract.1
new file mode 100644 (file)
index 0000000..5855d13
--- /dev/null
@@ -0,0 +1,25 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-extract 1  "extract " 
+.SH NAME
+debcargo\-extract \- Extract only a crate, without any other transformations
+.SH SYNOPSIS
+\fBdebcargo extract\fR [\fB\-\-config\fR] [\fB\-\-directory\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Extract only a crate, without any other transformations
+.SH OPTIONS
+.TP
+\fB\-\-config\fR \fI<CONFIG>\fR
+TOML file providing package\-specific options
+.TP
+\fB\-\-directory\fR \fI<DIRECTORY>\fR
+Output directory for the package. The orig tarball is named according to Debian conventions in the parent directory of this directory
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators. If empty string or omitted, resolves to the latest version
diff --git a/manpages/debcargo-package.1 b/manpages/debcargo-package.1
new file mode 100644 (file)
index 0000000..824a85d
--- /dev/null
@@ -0,0 +1,34 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-package 1  "package " 
+.SH NAME
+debcargo\-package \- Package a Rust crate for Debian
+.SH SYNOPSIS
+\fBdebcargo package\fR [\fB\-\-config\fR] [\fB\-\-directory\fR] [\fB\-\-changelog\-ready\fR] [\fB\-\-copyright\-guess\-harder\fR] [\fB\-\-no\-overlay\-write\-back\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fICRATE_NAME\fR> [\fIVERSION\fR] 
+.SH DESCRIPTION
+Package a Rust crate for Debian
+.SH OPTIONS
+.TP
+\fB\-\-config\fR \fI<CONFIG>\fR
+TOML file providing package\-specific options
+.TP
+\fB\-\-directory\fR \fI<DIRECTORY>\fR
+Output directory for the package. The orig tarball is named according to Debian conventions in the parent directory of this directory
+.TP
+\fB\-\-changelog\-ready\fR
+Assume the changelog is already bumped, and leave it alone
+.TP
+\fB\-\-copyright\-guess\-harder\fR
+Guess extra values for d/copyright. Might be slow
+.TP
+\fB\-\-no\-overlay\-write\-back\fR
+Don\*(Aqt write back hint files or d/changelog to the source overlay directory
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+<\fICRATE_NAME\fR>
+Name of the crate to package
+.TP
+[\fIVERSION\fR]
+Version of the crate to package; may contain dependency operators. If empty string or omitted, resolves to the latest version
diff --git a/manpages/debcargo-update.1 b/manpages/debcargo-update.1
new file mode 100644 (file)
index 0000000..695f033
--- /dev/null
@@ -0,0 +1,13 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo-update 1  "update " 
+.SH NAME
+debcargo\-update \- Update the user\*(Aqs default crates.io index, outside of a workspace
+.SH SYNOPSIS
+\fBdebcargo update\fR [\fB\-h\fR|\fB\-\-help\fR] 
+.SH DESCRIPTION
+Update the user\*(Aqs default crates.io index, outside of a workspace
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
diff --git a/manpages/debcargo.1 b/manpages/debcargo.1
new file mode 100644 (file)
index 0000000..bb59b64
--- /dev/null
@@ -0,0 +1,37 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH debcargo 1  "debcargo 2.7.11" 
+.SH NAME
+debcargo \- Package Rust crates for Debian.
+.SH SYNOPSIS
+\fBdebcargo\fR [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] <\fIsubcommands\fR>
+.SH DESCRIPTION
+Package Rust crates for Debian.
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print version
+.SH SUBCOMMANDS
+.TP
+debcargo\-update(1)
+Update the user\*(Aqs default crates.io index, outside of a workspace
+.TP
+debcargo\-deb\-src\-name(1)
+Print the Debian package name for a crate
+.TP
+debcargo\-extract(1)
+Extract only a crate, without any other transformations
+.TP
+debcargo\-package(1)
+Package a Rust crate for Debian
+.TP
+debcargo\-build\-order(1)
+Print the transitive dependencies of a package in topological order
+.TP
+debcargo\-deb\-dependencies(1)
+Print the dependencies of a package in d/control format
+.SH VERSION
+v2.7.11
diff --git a/src/bin/debcargo.rs b/src/bin/debcargo.rs
new file mode 100644 (file)
index 0000000..d84fcb8
--- /dev/null
@@ -0,0 +1,83 @@
+use ansi_term::Colour::Red;
+use clap::{crate_version, Parser};
+use itertools::Itertools;
+
+use debcargo::cli::{Cli, Opt};
+use debcargo::crates::CrateInfo;
+use debcargo::debian::DebInfo;
+use debcargo::errors::Result;
+use debcargo::package::*;
+use debcargo::{
+    build_order::build_order, crates::invalidate_crates_io_cache,
+    deb_dependencies::deb_dependencies,
+};
+
+#[test]
+fn verify_app() {
+    use clap::CommandFactory;
+    Cli::command().debug_assert()
+}
+
+fn real_main() -> Result<()> {
+    let m = Cli::parse();
+    use Opt::*;
+    match m.command {
+        Update => invalidate_crates_io_cache(),
+        DebSrcName {
+            crate_name,
+            version,
+        } => {
+            let crate_info = CrateInfo::new_with_update(&crate_name, version.as_deref(), false)?;
+            let deb_info = DebInfo::new(&crate_info, crate_version!(), version.is_some());
+            println!("{}", deb_info.package_name());
+            Ok(())
+        }
+        Extract { init, extract } => {
+            log::info!("preparing crate info");
+            let mut process = PackageProcess::init(init)?;
+            log::info!("extracting crate");
+            process.extract(extract)?;
+            Ok(())
+        }
+        Package {
+            init,
+            extract,
+            finish,
+        } => {
+            log::info!("preparing crate info");
+            let mut process = PackageProcess::init(init)?;
+            log::info!("extracting crate");
+            process.extract(extract)?;
+            log::info!("applying overlay and patches");
+            process.apply_overrides()?;
+            log::info!("preparing orig tarball");
+            process.prepare_orig_tarball()?;
+            log::info!("preparing debian folder");
+            process.prepare_debian_folder(finish)?;
+            process.post_package_checks()
+        }
+        BuildOrder { args } => {
+            let build_order = build_order(args)?;
+            for v in &build_order {
+                println!("{}", v);
+            }
+            Ok(())
+        }
+        DebDependencies { args } => {
+            let (toolchain_deps, dependencies) = deb_dependencies(args)?;
+            println!(
+                "{}",
+                toolchain_deps.into_iter().chain(dependencies).join(", ")
+            );
+            Ok(())
+        }
+    }
+}
+
+fn main() {
+    env_logger::init();
+    if let Err(e) = real_main() {
+        eprintln!("{}", Red.bold().paint(format!("debcargo failed: {:?}", e)));
+        std::process::exit(1);
+    }
+}
diff --git a/src/build_order.rs b/src/build_order.rs
new file mode 100644 (file)
index 0000000..27e7c26
--- /dev/null
@@ -0,0 +1,290 @@
+use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
+use std::fmt;
+use std::path::{Path, PathBuf};
+
+use anyhow::Context;
+use cargo::core::{Dependency, PackageId};
+use clap::{Parser, ValueEnum};
+
+use crate::config::Config;
+use crate::crates::{
+    all_dependencies_and_features, crate_name_ver_to_dep, show_dep, transitive_deps, CrateDepInfo,
+    CrateInfo,
+};
+use crate::debian::control::base_deb_name;
+use crate::errors::Result;
+use crate::package::{PackageExtractArgs, PackageProcess};
+use crate::util;
+
+#[derive(Debug, Clone, Copy, ValueEnum)]
+#[value(rename_all = "verbatim")]
+pub enum ResolveType {
+    SourceForDebianUnstable,
+    BinaryAllForDebianTesting,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct BuildOrderArgs {
+    /// Name of the crate to package.
+    crate_name: String,
+    /// Version of the crate to package; may contain dependency operators.
+    version: Option<String>,
+    /// Directory for configs. The config subdirectory for a given crate is
+    /// looked up by their crate name and version, from more specific to less
+    /// specific, e.g. <crate>-1.2.3, then <crate>-1.2, then <crate>-1 and
+    /// finally <crate>. The config file is read from the debian/debcargo.toml
+    /// subpath of the looked-up subdirectory.
+    #[arg(long)]
+    config_dir: Option<PathBuf>,
+    /// Resolution type
+    #[arg(value_enum, long, default_value = "SourceForDebianUnstable")]
+    resolve_type: ResolveType,
+    /// Emulate resolution as if every package were built with --collapse-features.
+    #[arg(long)]
+    emulate_collapse_features: bool,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+struct PackageIdFeat(PackageId, &'static str);
+
+impl fmt::Display for PackageIdFeat {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}@{}/{}", self.0.name(), self.0.version(), self.1)
+    }
+}
+
+// First result: if somebody build-depends on us, what do they first need to build?
+// Second result: what other packages need to go into Debian Testing before us?
+fn get_build_deps(
+    crate_details: &(CrateInfo, CrateDepInfo, Config),
+    package: &PackageIdFeat,
+    resolve_type: ResolveType,
+    emulate_collapse_features: bool,
+) -> Result<(Vec<Dependency>, Vec<Dependency>)> {
+    let (_, crate_dep_info, config) = crate_details;
+    let all_deps = crate_dep_info
+        .iter()
+        .flat_map(|(_, v)| v.1.iter())
+        .cloned()
+        .collect::<HashSet<_>>();
+    let feature_deps: HashSet<Dependency> =
+        HashSet::from_iter(transitive_deps(crate_dep_info, package.1)?.1);
+    let additional_deps = if emulate_collapse_features || config.collapse_features {
+        all_deps.clone()
+    } else {
+        // TODO: if build_depends_features is an override, use that instead of "default"
+        // TODO: also deprecate build_depends_excludes
+        HashSet::from_iter(transitive_deps(crate_dep_info, "default")?.1)
+    };
+    let hard_deps = feature_deps
+        .union(&additional_deps)
+        .cloned()
+        .collect::<Vec<_>>();
+    use ResolveType::*;
+    match resolve_type {
+        SourceForDebianUnstable => Ok((hard_deps, vec![])),
+        BinaryAllForDebianTesting => {
+            let mut soft_deps = all_deps;
+            for h in hard_deps.iter() {
+                soft_deps.remove(h);
+            }
+            Ok((hard_deps, soft_deps.into_iter().collect::<Vec<_>>()))
+        }
+    }
+}
+
+fn dep_features(dep: &Dependency) -> Vec<&'static str> {
+    let mut feats = dep
+        .features()
+        .iter()
+        .map(|x| x.as_str())
+        .collect::<Vec<_>>();
+    if dep.uses_default_features() {
+        feats.push("default")
+    }
+    feats.push(""); // bare-bones library with no features
+    feats
+}
+
+fn find_config(config_dir: &Path, id: PackageId) -> Result<(Option<PathBuf>, Config)> {
+    let name = base_deb_name(&id.name());
+    let version = id.version();
+    let candidates = [
+        format!(
+            "{}-{}.{}.{}",
+            name, version.major, version.minor, version.patch
+        ),
+        format!("{}-{}.{}", name, version.major, version.minor),
+        format!("{}-{}", name, version.major),
+        name,
+    ];
+    for c in candidates {
+        let path = config_dir.join(c).join("debian").join("debcargo.toml");
+        if path.is_file() {
+            let config = Config::parse(&path).context("failed to parse debcargo.toml")?;
+            log::debug!("using config for {}: {:?}", id, path);
+            return Ok((Some(path), config));
+        }
+    }
+    Ok((None, Config::default()))
+}
+
+fn resolve_info(
+    infos: &mut BTreeMap<PackageId, (CrateInfo, CrateDepInfo, Config)>,
+    cache: &mut HashMap<Dependency, PackageId>,
+    config_dir: Option<&Path>,
+    dependency: &Dependency,
+    update: bool,
+) -> Result<PackageId> {
+    if let Some(id) = cache.get(dependency) {
+        return Ok(*id);
+    }
+
+    // resolve dependency
+    let info = CrateInfo::new_from_dependency(dependency, update)?;
+    let id = info.package_id();
+    cache.insert(dependency.clone(), id);
+
+    // insert info if it's not already there
+    if let std::collections::btree_map::Entry::Vacant(e) = infos.entry(id) {
+        let id = *e.key();
+        let default_config = Config::default();
+        let (config_path, config) = match config_dir {
+            None => (None, default_config),
+            Some(config_dir) => {
+                let (config_path, config) = find_config(config_dir, id)?;
+                match config_path {
+                    None => (None, default_config),
+                    Some(_) => (config_path, config),
+                }
+            }
+        };
+        let (info, config) = match config_path {
+            None => (info, config),
+            Some(_) => {
+                let mut process = PackageProcess::new(info, config_path, config)?;
+                let tempdir = tempfile::Builder::new()
+                    .prefix("debcargo")
+                    .tempdir_in(".")?;
+                process.extract(PackageExtractArgs {
+                    directory: Some(tempdir.path().to_path_buf()),
+                })?;
+                process.apply_overrides()?;
+                (process.crate_info, process.config)
+            }
+        };
+        let dep_info = all_dependencies_and_features(info.manifest());
+        e.insert((info, dep_info, config));
+    };
+    Ok(id)
+}
+
+pub fn build_order(args: BuildOrderArgs) -> Result<Vec<PackageId>> {
+    let crate_name = &args.crate_name;
+    let version = args.version.as_deref();
+    let config_dir = args.config_dir.as_deref();
+
+    let mut infos = BTreeMap::new();
+    let mut cache = HashMap::new();
+    let seed_dep = crate_name_ver_to_dep(crate_name, version)?;
+    let seed_id = resolve_info(&mut infos, &mut cache, config_dir, &seed_dep, true)?;
+
+    let mut next = |idf: &PackageIdFeat| -> Result<(Vec<PackageIdFeat>, Vec<PackageIdFeat>)> {
+        log::trace!("{} getting build deps..", idf);
+        let (hard, soft) = get_build_deps(
+            infos
+                .get(&idf.0)
+                .expect("build_order next called without crate info"),
+            idf,
+            args.resolve_type,
+            args.emulate_collapse_features,
+        )?;
+        log::trace!("{} hard-dep: {}", idf, util::show_vec_with(&hard, show_dep));
+        if !soft.is_empty() {
+            log::trace!("{} soft-dep: {}", idf, util::show_vec_with(&soft, show_dep));
+        }
+        // note: we might resolve the same crate-version several times;
+        // this is expected, since different dependencies (with different
+        // version ranges) might resolve into the same crate-version
+        let mut hard_p = Vec::new();
+        for dep in hard {
+            let id = resolve_info(&mut infos, &mut cache, config_dir, &dep, false)?;
+            for f in dep_features(&dep) {
+                hard_p.push(PackageIdFeat(id, f));
+            }
+        }
+        let mut soft_p = Vec::new();
+        for dep in soft {
+            let id = resolve_info(&mut infos, &mut cache, config_dir, &dep, false)?;
+            for f in dep_features(&dep) {
+                soft_p.push(PackageIdFeat(id, f));
+            }
+        }
+        log::trace!("{} hard-dep resolve: {}", idf, util::show_vec(&hard_p));
+        if !soft_p.is_empty() {
+            log::trace!("{} soft-dep resolve: {}", idf, util::show_vec(&soft_p));
+        }
+        Ok((hard_p, soft_p))
+    };
+    let mut i = 0;
+    let mut log = |remaining: &VecDeque<_>, graph: &BTreeMap<_, _>| {
+        i += 1;
+        if i % 16 == 0 {
+            debcargo_info!(
+                "debcargo build-order: resolving dependencies: done: {}, todo: {}",
+                graph.len(),
+                remaining.len()
+            );
+        }
+        Ok(())
+    };
+
+    let succ_with_features =
+        util::graph_from_succ([PackageIdFeat(seed_id, "")], &mut next, &mut log)?;
+    log::trace!("succ_with_features: {:#?}", succ_with_features);
+
+    let succ = util::succ_proj(&succ_with_features, |x| x.0);
+    let pred = util::succ_to_pred(&succ);
+    let roots = succ
+        .iter()
+        .filter_map(|(k, v)| if v.is_empty() { Some(*k) } else { None })
+        .collect::<BTreeSet<_>>();
+    // swap pred/succ for call to topo_sort since we want reverse topo order
+    let build_order = match util::topo_sort(roots, pred.clone(), succ.clone()) {
+        Ok(r) => r,
+        Err(remain) => {
+            log::error!(
+                "topo_sort got cyclic graph: {:#?}",
+                remain
+                    .into_iter()
+                    .map(|(k, vv)| (
+                        k.to_string(),
+                        vv.into_iter()
+                            .map(|v| v.to_string())
+                            .collect::<BTreeSet<_>>()
+                    ))
+                    .collect::<BTreeMap<_, _>>()
+            );
+            debcargo_bail!(
+                "topo_sort got cyclic graph; you'll need to patch the crate(s) to break the cycle."
+            )
+        }
+    };
+
+    // sanity check
+    for p in build_order.iter() {
+        if infos.remove(p).is_none() {
+            log::error!("extra package in build-order not in infos: {}", p);
+        }
+    }
+    for (p, _) in infos {
+        log::error!(
+            "leftover infos not used in build-order: {}, succ: {}, pred: {}",
+            p,
+            util::show_vec(succ.get(&p).into_iter().flatten()),
+            util::show_vec(pred.get(&p).into_iter().flatten()),
+        );
+    }
+
+    Ok(build_order)
+}
diff --git a/src/cli.rs b/src/cli.rs
new file mode 100644 (file)
index 0000000..4e0d2ad
--- /dev/null
@@ -0,0 +1,64 @@
+use clap::{builder::styling::AnsiColor, builder::Styles, Parser, Subcommand};
+
+use crate::{
+    build_order::BuildOrderArgs,
+    deb_dependencies::DebDependenciesArgs,
+    package::{PackageExecuteArgs, PackageExtractArgs, PackageInitArgs},
+};
+
+const CLI_STYLE: Styles = Styles::styled()
+    .header(AnsiColor::Yellow.on_default())
+    .usage(AnsiColor::Green.on_default())
+    .literal(AnsiColor::Green.on_default())
+    .placeholder(AnsiColor::Green.on_default());
+
+#[derive(Debug, Clone, Parser)]
+#[command(name = "debcargo", about = "Package Rust crates for Debian.")]
+#[command(version)]
+#[command(styles = CLI_STYLE)]
+pub struct Cli {
+    #[command(subcommand)]
+    pub command: Opt,
+}
+
+#[derive(Debug, Clone, Subcommand)]
+pub enum Opt {
+    /// Update the user's default crates.io index, outside of a workspace.
+    Update,
+    /// Print the Debian package name for a crate.
+    DebSrcName {
+        /// Name of the crate to package.
+        crate_name: String,
+        /// Version of the crate to package; may contain dependency operators.
+        /// If empty string, resolves to the latest version. If given here,
+        /// i.e. not omitted then print the package name as if the config
+        /// option semver_suffix was set to true.
+        version: Option<String>,
+    },
+    /// Extract only a crate, without any other transformations.
+    Extract {
+        #[command(flatten)]
+        init: PackageInitArgs,
+        #[command(flatten)]
+        extract: PackageExtractArgs,
+    },
+    /// Package a Rust crate for Debian.
+    Package {
+        #[command(flatten)]
+        init: PackageInitArgs,
+        #[command(flatten)]
+        extract: PackageExtractArgs,
+        #[command(flatten)]
+        finish: PackageExecuteArgs,
+    },
+    /// Print the transitive dependencies of a package in topological order.
+    BuildOrder {
+        #[command(flatten)]
+        args: BuildOrderArgs,
+    },
+    /// Print the dependencies of a package in d/control format
+    DebDependencies {
+        #[command(flatten)]
+        args: DebDependenciesArgs,
+    },
+}
diff --git a/src/config.rs b/src/config.rs
new file mode 100644 (file)
index 0000000..76efd2d
--- /dev/null
@@ -0,0 +1,367 @@
+use serde::Deserialize;
+use toml;
+
+use crate::errors::*;
+
+use std::collections::HashMap;
+use std::fs::File;
+use std::io::Read;
+use std::path::{Path, PathBuf};
+
+pub const RUST_MAINT: &str =
+    "Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>";
+
+#[derive(Deserialize, Debug, Clone)]
+#[serde(default)]
+pub struct Config {
+    pub bin: Option<bool>,
+    pub bin_name: String,
+    pub semver_suffix: bool,
+    pub overlay: Option<PathBuf>,
+    pub excludes: Option<Vec<String>>,
+    pub whitelist: Option<Vec<String>>,
+    pub allow_prerelease_deps: bool,
+    pub crate_src_path: Option<PathBuf>,
+    pub summary: Option<String>,
+    pub description: Option<String>,
+    pub maintainer: String,
+    pub uploaders: Option<Vec<String>>,
+    pub collapse_features: bool,
+    pub requires_root: Option<String>,
+
+    pub source: Option<SourceOverride>,
+    pub packages: HashMap<String, PackageOverride>,
+
+    #[serde(flatten)]
+    pub unknown_fields: HashMap<String, toml::Value>,
+}
+
+#[derive(Deserialize, Debug, Clone, Default)]
+pub struct SourceOverride {
+    section: Option<String>,
+    policy: Option<String>,
+    homepage: Option<String>,
+    vcs_git: Option<String>,
+    vcs_browser: Option<String>,
+    build_depends: Option<Vec<String>>,
+    build_depends_arch: Option<Vec<String>>,
+    build_depends_indep: Option<Vec<String>>,
+    build_depends_excludes: Option<Vec<String>>,
+    skip_nocheck: Option<bool>,
+
+    #[serde(flatten)]
+    pub unknown_fields: HashMap<String, toml::Value>,
+}
+
+impl SourceOverride {
+    pub fn new(
+        section: Option<String>,
+        policy: Option<String>,
+        homepage: Option<String>,
+        vcs_git: Option<String>,
+        vcs_browser: Option<String>,
+        build_depends: Option<Vec<String>>,
+        build_depends_arch: Option<Vec<String>>,
+        build_depends_indep: Option<Vec<String>>,
+        build_depends_excludes: Option<Vec<String>>,
+        skip_nocheck: Option<bool>,
+    ) -> Self {
+        Self {
+            section,
+            policy,
+            homepage,
+            vcs_git,
+            vcs_browser,
+            build_depends,
+            build_depends_arch,
+            build_depends_indep,
+            build_depends_excludes,
+            skip_nocheck,
+            unknown_fields: HashMap::new(),
+        }
+    }
+}
+#[derive(Deserialize, Debug, Clone, Default)]
+pub struct PackageOverride {
+    section: Option<String>,
+    summary: Option<String>,
+    description: Option<String>,
+    architecture: Option<Vec<String>>,
+    multi_arch: Option<String>,
+    depends: Option<Vec<String>>,
+    recommends: Option<Vec<String>>,
+    suggests: Option<Vec<String>>,
+    provides: Option<Vec<String>>,
+    breaks: Option<Vec<String>>,
+    replaces: Option<Vec<String>>,
+    conflicts: Option<Vec<String>>,
+    extra_lines: Option<Vec<String>>,
+    test_is_broken: Option<bool>,
+    test_architecture: Option<Vec<String>>,
+    test_depends: Option<Vec<String>>,
+
+    #[serde(flatten)]
+    pub unknown_fields: HashMap<String, toml::Value>,
+}
+
+impl Default for Config {
+    fn default() -> Self {
+        Config {
+            bin: None,
+            bin_name: "<default>".to_string(),
+            semver_suffix: false,
+            overlay: None,
+            excludes: None,
+            whitelist: None,
+            allow_prerelease_deps: false,
+            crate_src_path: None,
+            summary: None,
+            description: None,
+            maintainer: RUST_MAINT.to_string(),
+            uploaders: None,
+            collapse_features: false,
+            source: None,
+            packages: HashMap::new(),
+            requires_root: None,
+            unknown_fields: HashMap::new(),
+        }
+    }
+}
+
+impl Config {
+    pub fn parse(src: &Path) -> Result<Config> {
+        let mut config_file = File::open(src)?;
+        let mut content = String::new();
+        config_file.read_to_string(&mut content)?;
+
+        let config: Config = toml::from_str(&content)?;
+
+        let mut unknown_fields = Vec::new();
+
+        for field in config.unknown_fields.keys() {
+            unknown_fields.push(field.clone());
+        }
+
+        if let Some(ref source) = config.source {
+            for field in source.unknown_fields.keys() {
+                unknown_fields.push(format!("source.{}", field));
+            }
+        }
+
+        for (name, package) in &config.packages {
+            for field in package.unknown_fields.keys() {
+                unknown_fields.push(format!("packages.{}.{}", name, field));
+            }
+        }
+
+        if !unknown_fields.is_empty() {
+            debcargo_warn!(
+                "Warning: Unknown fields in {}: {:?}",
+                src.display(),
+                unknown_fields
+            );
+            debcargo_warn!("         These fields will be ignored. Please check for typos.");
+        }
+
+        Ok(config)
+    }
+
+    pub fn build_bin_package(&self) -> bool {
+        match self.bin {
+            None => !self.semver_suffix,
+            Some(b) => b,
+        }
+    }
+
+    pub fn overlay_dir(&self, config_path: Option<&Path>) -> Option<PathBuf> {
+        Some(config_path?.parent()?.join(self.overlay.as_ref()?))
+    }
+
+    pub fn crate_src_path(&self, config_path: Option<&Path>) -> Option<PathBuf> {
+        Some(config_path?.parent()?.join(self.crate_src_path.as_ref()?))
+    }
+
+    pub fn orig_tar_excludes(&self) -> Option<&Vec<String>> {
+        self.excludes.as_ref()
+    }
+
+    pub fn orig_tar_whitelist(&self) -> Option<&Vec<String>> {
+        self.whitelist.as_ref()
+    }
+
+    pub fn maintainer(&self) -> &str {
+        self.maintainer.as_str()
+    }
+
+    pub fn uploaders(&self) -> Option<&Vec<String>> {
+        self.uploaders.as_ref()
+    }
+
+    pub fn requires_root(&self) -> Option<&String> {
+        self.requires_root.as_ref()
+    }
+
+    // Source shortcuts
+
+    pub fn section(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.section.as_ref()?)
+    }
+
+    pub fn policy_version(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.policy.as_ref()?)
+    }
+
+    pub fn homepage(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.homepage.as_ref()?)
+    }
+
+    pub fn vcs_git(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.vcs_git.as_ref()?)
+    }
+
+    pub fn vcs_browser(&self) -> Option<&str> {
+        Some(self.source.as_ref()?.vcs_browser.as_ref()?)
+    }
+
+    pub fn build_depends(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends.as_ref()
+    }
+
+    pub fn build_depends_arch(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends_arch.as_ref()
+    }
+
+    pub fn build_depends_indep(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends_indep.as_ref()
+    }
+
+    pub fn build_depends_excludes(&self) -> Option<&Vec<String>> {
+        self.source.as_ref()?.build_depends_excludes.as_ref()
+    }
+
+    pub fn skip_nocheck(&self) -> Option<bool> {
+        self.source.as_ref()?.skip_nocheck
+    }
+
+    // Packages shortcuts
+
+    fn with_package<'a, T, F: FnOnce(&'a PackageOverride) -> Option<T>>(
+        &'a self,
+        key: PackageKey,
+        f: F,
+    ) -> Option<T> {
+        self.packages.get(&package_key_string(key)).and_then(f)
+    }
+
+    pub fn package_section(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.section.as_deref())
+    }
+
+    pub fn package_summary(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.summary.as_deref())
+    }
+
+    pub fn package_description(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.description.as_deref())
+    }
+
+    pub fn package_architecture(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.architecture.as_ref())
+    }
+
+    pub fn package_multi_arch(&self, key: PackageKey) -> Option<&str> {
+        self.with_package(key, |pkg| pkg.multi_arch.as_deref())
+    }
+
+    pub fn package_depends(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.depends.as_ref())
+    }
+
+    pub fn package_recommends(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.recommends.as_ref())
+    }
+
+    pub fn package_suggests(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.suggests.as_ref())
+    }
+
+    pub fn package_provides(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.provides.as_ref())
+    }
+
+    pub fn package_breaks(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.breaks.as_ref())
+    }
+
+    pub fn package_replaces(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.replaces.as_ref())
+    }
+
+    pub fn package_conflicts(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.conflicts.as_ref())
+    }
+
+    pub fn package_extra_lines(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.extra_lines.as_ref())
+    }
+
+    pub fn package_test_is_broken(&self, key: PackageKey) -> Option<bool> {
+        self.with_package(key, |pkg| pkg.test_is_broken)
+    }
+
+    pub fn package_test_architecture(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.test_architecture.as_ref())
+    }
+
+    pub fn package_test_depends(&self, key: PackageKey) -> Option<&Vec<String>> {
+        self.with_package(key, |pkg| pkg.test_depends.as_ref())
+    }
+}
+
+pub fn package_field_for_feature<'a>(
+    get_field: &'a dyn Fn(PackageKey) -> Option<&'a Vec<String>>,
+    feature: PackageKey,
+    f_provides: &[&str],
+) -> Vec<String> {
+    Some(feature)
+        .into_iter()
+        .chain(f_provides.iter().map(|s| PackageKey::feature(s)))
+        .flat_map(move |f| get_field(f).into_iter().flatten())
+        .map(|s| s.to_string())
+        .collect()
+}
+
+#[derive(Clone, Copy)]
+pub enum PackageKey<'a> {
+    Bin,
+    BareLib,
+    FeatureLib(&'a str),
+}
+
+impl<'a> PackageKey<'a> {
+    pub fn feature(f: &'a str) -> PackageKey<'a> {
+        use self::PackageKey::*;
+        if f.is_empty() {
+            BareLib
+        } else {
+            FeatureLib(f)
+        }
+    }
+}
+
+fn package_key_string(key: PackageKey) -> String {
+    use self::PackageKey::*;
+    match key {
+        Bin => "bin".to_string(),
+        BareLib => "lib".to_string(),
+        FeatureLib(feature) => format!("lib+{}", feature),
+    }
+}
+
+pub fn testing_ignore_debpolv() -> bool {
+    std::env::var("DEBCARGO_TESTING_IGNORE_DEBIAN_POLICY_VIOLATION") == Ok("1".to_string())
+}
+
+pub fn testing_ruzt() -> bool {
+    std::env::var("DEBCARGO_TESTING_RUZT") == Ok("1".to_string())
+}
diff --git a/src/crates.rs b/src/crates.rs
new file mode 100644 (file)
index 0000000..3f28977
--- /dev/null
@@ -0,0 +1,868 @@
+use anyhow::{format_err, Error};
+use cargo::{
+    core::{
+        manifest::ManifestMetadata, registry::PackageRegistry, resolver::features::CliFeatures,
+        Dependency, EitherManifest, FeatureValue, Manifest, Package, PackageId, Registry, SourceId,
+        Summary, Target, TargetKind, Workspace,
+    },
+    ops::{self, PackageOpts, Packages},
+    sources::{
+        source::{MaybePackage, QueryKind, Source},
+        IndexSummary, RegistrySource, SourceConfigMap,
+    },
+    util::{
+        cache_lock::CacheLockMode, interning::InternedString, toml::read_manifest, FileLock,
+        GlobalContext,
+    },
+};
+use filetime::{set_file_times, FileTime};
+use flate2::read::GzDecoder;
+use glob::Pattern;
+use itertools::Itertools;
+use regex::Regex;
+use semver::Version;
+use tar::Archive;
+use tempfile;
+
+use std::collections::{BTreeMap, HashSet};
+use std::fs;
+use std::io::{self, Read};
+use std::path::Path;
+use std::{self, ffi::OsStr};
+
+use crate::config::testing_ignore_debpolv;
+use crate::errors::*;
+
+pub struct CrateInfo {
+    // only used for to_registry_toml in extract_crate. DO NOT USE ELSEWHERE
+    package: Package,
+    // allows overriding package.manifest() e.g. via patches
+    manifest: Manifest,
+    crate_file: FileLock,
+    context: GlobalContext,
+    source_id: SourceId,
+    excludes: Vec<String>,
+    includes: Vec<String>,
+}
+
+pub type CrateDepInfo = BTreeMap<
+    &'static str, // name of feature / optional dependency,
+    // or "" for the base package w/ no default features, guaranteed to be in the map
+    (
+        Vec<&'static str>, // dependencies: other features (of the current package)
+        Vec<Dependency>,
+    ),
+>;
+
+fn fetch_candidates(registry: &mut PackageRegistry, dep: &Dependency) -> Result<Vec<IndexSummary>> {
+    let mut summaries = match registry.query_vec(dep, QueryKind::Exact) {
+        std::task::Poll::Ready(res) => res?,
+        std::task::Poll::Pending => {
+            registry.block_until_ready()?;
+            return fetch_candidates(registry, dep);
+        }
+    };
+    summaries.sort_by(|a, b| b.package_id().partial_cmp(&a.package_id()).unwrap());
+    Ok(summaries)
+}
+
+pub fn invalidate_crates_io_cache() -> Result<()> {
+    let context = GlobalContext::default()?;
+    let _lock = context.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
+    let source_id = SourceId::crates_io_maybe_sparse_http(&context)?;
+    let yanked_whitelist = HashSet::new();
+    let mut r = RegistrySource::remote(source_id, &yanked_whitelist, &context)?;
+    r.invalidate_cache();
+    Ok(())
+}
+
+pub fn crate_name_ver_to_dep(crate_name: &str, version: Option<&str>) -> Result<Dependency> {
+    // note: this forces a network call
+    let context = GlobalContext::default()?;
+    let source_id = SourceId::crates_io_maybe_sparse_http(&context)?;
+    let version = version.and_then(|v| {
+        if v.is_empty() {
+            None
+        } else if v.starts_with(|c: char| c.is_ascii_digit()) {
+            Some(["=", v].concat())
+        } else {
+            Some(v.to_string())
+        }
+    });
+    Dependency::parse(crate_name, version.as_deref(), source_id)
+}
+
+// attempt to map back a version requirement to a version that can be used as last resort
+// fallback in case all versions satisfying the requirement are yanked
+fn ver_req_to_ver(dep: &Dependency) -> Option<Version> {
+    match dep.version_req() {
+        // if any version would satisfy the dep, but all of them are yanked, we probably don't want
+        // to use this crate anyway ;)
+        cargo::util::OptVersionReq::Any => None,
+        // a regular version requirement is only useful if it has a single element
+        cargo::util::OptVersionReq::Req(req) if req.comparators.len() == 1 => {
+            let comp = req.comparators.first().unwrap();
+            match comp.op {
+                // these are all satisfied by the full version, if one is set
+                semver::Op::Exact
+                | semver::Op::GreaterEq
+                | semver::Op::LessEq
+                | semver::Op::Tilde
+                | semver::Op::Caret => {
+                    if let Some(minor) = comp.minor {
+                        // if the requirement comes with a full version extract it
+                        comp.patch.map(|patch| Version {
+                            major: comp.major,
+                            minor,
+                            patch,
+                            pre: comp.pre.clone(),
+                            build: semver::BuildMetadata::default(),
+                        })
+                    } else {
+                        // we'd have to guess here.
+                        None
+                    }
+                }
+                // Greater, Less or Wildcard all require guessing as well
+                _ => None,
+            }
+        }
+        // requirements with multiple constraints
+        cargo::util::OptVersionReq::Req(_) => None,
+        // locked requirements contain an exact version
+        cargo::util::OptVersionReq::Locked(ver, _) => Some(ver.clone()),
+        // precise requirements contain an exact version
+        cargo::util::OptVersionReq::Precise(ver, _) => Some(ver.clone()),
+    }
+}
+
+pub fn show_dep(dep: &Dependency) -> String {
+    format!("{} {}", dep.package_name(), dep.version_req())
+}
+
+impl CrateInfo {
+    pub fn new(crate_name: &str, version: Option<&str>) -> Result<CrateInfo> {
+        CrateInfo::new_with_update(crate_name, version, true)
+    }
+
+    pub fn new_with_local_crate(
+        crate_name: &str,
+        version: Option<&str>,
+        crate_path: &Path,
+    ) -> Result<CrateInfo> {
+        let context = GlobalContext::default()?;
+        let crate_path = crate_path.canonicalize()?;
+        let source_id = SourceId::for_path(&crate_path)?;
+
+        let (package, crate_file) = {
+            let yanked_whitelist = HashSet::new();
+
+            let mut source = source_id.load(&context, &yanked_whitelist)?;
+
+            let package_id = match version {
+                None => {
+                    let dep = Dependency::parse(crate_name, None, source_id)?;
+                    let mut package_id: Option<PackageId> = None;
+                    loop {
+                        match source.query(&dep, QueryKind::Exact, &mut |p| {
+                            package_id = Some(p.package_id())
+                        }) {
+                            std::task::Poll::Ready(res) => {
+                                res?;
+                                break;
+                            }
+                            std::task::Poll::Pending => {
+                                source.block_until_ready()?;
+                            }
+                        }
+                    }
+                    package_id.unwrap()
+                }
+                Some(version) => {
+                    let version = version.parse::<Version>()?;
+                    PackageId::new(crate_name.into(), version, source_id)
+                }
+            };
+
+            let maybe_package = source.download(package_id)?;
+            let package = match maybe_package {
+                MaybePackage::Ready(p) => Ok(p),
+                _ => Err(format_err!(
+                    "Failed to 'download' local crate {} from {}",
+                    crate_name,
+                    crate_path.display()
+                )),
+            }?;
+
+            let crate_file = {
+                let workspace = Workspace::ephemeral(package.clone(), &context, None, true)?;
+
+                let opts = PackageOpts {
+                    gctx: &context,
+                    verify: false,
+                    list: false,
+                    check_metadata: true,
+                    allow_dirty: true,
+                    cli_features: CliFeatures::from_command_line(&[], true, false)?,
+                    jobs: None,
+                    targets: Vec::new(),
+                    to_package: Packages::Default,
+                    keep_going: false,
+                    reg_or_index: None,
+                };
+                ops::package(&workspace, &opts)?;
+
+                let filename = format!("{}-{}.crate", crate_name, package_id.version());
+                workspace
+                    .target_dir()
+                    .join("package")
+                    .open_rw_exclusive_create(filename, &context, "crate file")?
+            };
+
+            (package, crate_file)
+        };
+
+        let manifest = package.manifest().clone();
+
+        Ok(CrateInfo {
+            package,
+            manifest,
+            crate_file,
+            context,
+            source_id,
+            excludes: vec![],
+            includes: vec![],
+        })
+    }
+
+    pub fn new_with_update(
+        crate_name: &str,
+        version: Option<&str>,
+        update: bool,
+    ) -> Result<CrateInfo> {
+        let dep = crate_name_ver_to_dep(crate_name, version)?;
+        Self::new_from_dependency(&dep, update)
+    }
+
+    pub fn new_from_dependency(dependency: &Dependency, update: bool) -> Result<CrateInfo> {
+        let mut context = GlobalContext::default()?;
+        if !update {
+            // unfriendly API from cargo; we'll have to make do with it for
+            // now as there is no other alternative
+            context.configure(
+                0,
+                false,
+                None,
+                context.frozen(),
+                context.locked(),
+                true, // offline
+                &context.target_dir()?.map(|x| x.into_path_unlocked()),
+                &[],
+                &[],
+            )?;
+        }
+
+        let source_id = SourceId::crates_io_maybe_sparse_http(&context)?;
+        let registry_name = format!(
+            "{}-{}",
+            source_id.url().host_str().unwrap_or(""),
+            cargo::util::hex::short_hash(&source_id)
+        );
+        let get_package_info = |context: &GlobalContext,
+                                possibly_yanked_ver: Option<&Version>|
+         -> Result<_> {
+            let lock = context.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
+            let mut registry =
+                PackageRegistry::new_with_source_config(context, SourceConfigMap::new(context)?)?;
+
+            // if we have some exact version that should satisfy our dependency requirements, and
+            // we are on our third attempt of retrieving the crate info from the registry, add this
+            // version to the yanked whitelist as a last resort
+            if let Some(ver) = possibly_yanked_ver {
+                let pkgids = vec![PackageId::new(
+                    dependency.package_name(),
+                    ver.clone(),
+                    dependency.source_id(),
+                )];
+                debcargo_warn!(
+                    "Adding {} to yanked whitelist as last resort..",
+                    pkgids.first().unwrap()
+                );
+                registry.add_to_yanked_whitelist(pkgids.into_iter());
+            }
+            registry.lock_patches();
+            let summaries = fetch_candidates(&mut registry, dependency)?;
+            drop(lock);
+            let pkgids = summaries.into_iter().map(|s| s.package_id()).collect_vec();
+            let pkgid = pkgids.iter().max().ok_or_else(|| {
+                format_err!(
+                    concat!(
+                        "Couldn't find any crate matching {}\n",
+                        "Try `debcargo update` to update the crates.io index."
+                    ),
+                    show_dep(dependency)
+                )
+            })?;
+            let pkgset = registry.get(pkgids.as_slice())?;
+            let package = pkgset.get_one(*pkgid)?;
+
+            let manifest = package.manifest();
+            for f in dependency.features() {
+                // apparently, if offline is set then cargo sometimes selects
+                // an offline-available version that doesn't satisfy the
+                // requested features. this is dumb. if it happens, then we
+                // retry with online allowed.
+                if !manifest.summary().features().contains_key(f) {
+                    debcargo_bail!(
+                        "resolve ({} {}) -> ({}) failed to pick up required feature ({})\n\
+                        This can happen with very old or yanked crates. Try patching one of \
+                        its dependants, to drop or update the offending dependency.",
+                        dependency.package_name(),
+                        dependency.version_req(),
+                        pkgid,
+                        f,
+                    )
+                }
+            }
+            let filename = format!("{}-{}.crate", pkgid.name(), pkgid.version());
+            let crate_file = context
+                .registry_cache_path()
+                .join(&registry_name)
+                .open_ro_shared(&filename, context, &filename)?;
+            Ok((package.clone(), manifest.clone(), crate_file))
+        };
+        // if update is false but the user never downloaded the crate then the
+        // first call will error; re-try with online in that case
+        let (package, manifest, crate_file) = get_package_info(&context, None)
+            .or_else(|_| get_package_info(&GlobalContext::default()?, None))
+            .or_else(|err| {
+                let ver = ver_req_to_ver(dependency);
+                if ver.is_some() {
+                    get_package_info(&GlobalContext::default()?, ver.as_ref())
+                } else {
+                    Err(err)
+                }
+            })?;
+
+        Ok(CrateInfo {
+            package,
+            manifest,
+            crate_file,
+            context,
+            source_id,
+            excludes: vec![],
+            includes: vec![],
+        })
+    }
+
+    pub fn crate_name(&self) -> &'static str {
+        self.package_id().name().as_str()
+    }
+
+    pub fn version(&self) -> &Version {
+        self.package_id().version()
+    }
+
+    pub fn semver(&self) -> String {
+        match *self.package_id().version() {
+            Version {
+                major: 0, minor, ..
+            } => format!("0.{}", minor),
+            Version { major, .. } => format!("{}", major),
+        }
+    }
+
+    pub fn manifest(&self) -> &Manifest {
+        &self.manifest
+    }
+
+    pub fn replace_manifest(&mut self, path: &Path) -> Result<&Self> {
+        if let EitherManifest::Real(v) = read_manifest(path, self.source_id, &self.context)? {
+            self.manifest = v;
+        }
+        Ok(self)
+    }
+
+    pub fn metadata(&self) -> &ManifestMetadata {
+        self.manifest.metadata()
+    }
+
+    pub fn manifest_path(&self) -> &Path {
+        self.package.manifest_path()
+    }
+
+    pub fn rust_version(&self) -> Option<String> {
+        self.manifest.rust_version().map(|v| v.to_string())
+    }
+
+    pub fn targets(&self) -> &[Target] {
+        self.manifest.targets()
+    }
+
+    pub fn is_lib(&self) -> bool {
+        let mut lib = false;
+        for target in self.manifest.targets() {
+            match *target.kind() {
+                TargetKind::Lib(_) => {
+                    lib = true;
+                    break;
+                }
+                _ => continue,
+            }
+        }
+        lib
+    }
+
+    pub fn get_binary_targets(&self) -> Vec<&str> {
+        let mut bins = Vec::new();
+        for target in self.manifest.targets() {
+            match *target.kind() {
+                TargetKind::Bin => {
+                    bins.push(target.name());
+                }
+                _ => continue,
+            }
+        }
+        bins.sort_unstable();
+        bins
+    }
+
+    pub fn summary(&self) -> &Summary {
+        self.manifest.summary()
+    }
+
+    pub fn checksum(&self) -> Option<&str> {
+        self.manifest.summary().checksum()
+    }
+
+    pub fn package_id(&self) -> PackageId {
+        self.manifest.summary().package_id()
+    }
+
+    pub fn crate_file(&self) -> &FileLock {
+        &self.crate_file
+    }
+
+    pub fn dependencies(&self) -> &[Dependency] {
+        self.manifest.dependencies()
+    }
+
+    pub fn dev_dependencies(&self) -> Vec<Dependency> {
+        use cargo::core::dependency::DepKind;
+        let mut deps = vec![];
+        for dep in self.dependencies() {
+            if dep.kind() == DepKind::Development {
+                deps.push(dep.clone())
+            }
+        }
+        deps
+    }
+
+    pub fn get_summary_description(&self) -> (Option<String>, Option<String>) {
+        let (summary, description) = if let Some(ref description) = self.metadata().description {
+            // Convention these days seems to be to do manual text
+            // wrapping in crate descriptions, boo. \n\n is a real line break.
+            let mut description = description
+                .replace("\n\n", "\r")
+                .replace('\n', " ")
+                .replace('\r', "\n")
+                .trim()
+                .to_string();
+            // Trim off common prefixes
+            let re = Regex::new(&format!(
+                r"^(?i)({}|This(\s+\w+)?)(\s*,|\s+is|\s+provides)\s+",
+                self.package_id().name()
+            ))
+            .unwrap();
+            description = re.replace(&description, "").to_string();
+            let re = Regex::new(r"^(?i)(a|an|the)\s+").unwrap();
+            description = re.replace(&description, "").to_string();
+            let re =
+                Regex::new(r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+")
+                    .unwrap();
+            description = re.replace(&description, "").to_string();
+
+            // https://stackoverflow.com/questions/38406793/why-is-capitalizing-the-first-letter-of-a-string-so-convoluted-in-rust
+            description = {
+                let mut d = description.chars();
+                match d.next() {
+                    None => String::new(),
+                    Some(f) => f.to_uppercase().chain(d).collect::<String>(),
+                }
+            };
+
+            // Use the first sentence or first line, whichever comes first, as the summary.
+            let p1 = description.find('\n');
+            let p2 = description.find(". ");
+            match p1.into_iter().chain(p2).min() {
+                Some(p) => {
+                    let s = description[..p].trim_end_matches('.').to_string();
+                    let d = description[p + 1..].trim();
+                    if d.is_empty() {
+                        (Some(s), None)
+                    } else {
+                        (Some(s), Some(d.to_string()))
+                    }
+                }
+                None => (Some(description.trim_end_matches('.').to_string()), None),
+            }
+        } else {
+            (None, None)
+        };
+
+        (summary, description)
+    }
+
+    /// To be called before extract_crate.
+    pub fn set_includes_excludes(
+        &mut self,
+        excludes: Option<&Vec<String>>,
+        includes: Option<&Vec<String>>,
+    ) {
+        self.excludes = excludes.cloned().unwrap_or_default();
+        self.includes = includes.cloned().unwrap_or_default();
+    }
+
+    pub fn filter_path(&self, path: &Path) -> std::result::Result<bool, String> {
+        let top_level = path
+            .ancestors()
+            .find(|p| p.parent() == Some(Path::new("")))
+            .unwrap()
+            .to_str()
+            .ok_or_else(|| format!("Failed to get top-level element of {path:?}"))?;
+
+        let matches = move |pattern: &String| -> bool {
+            Pattern::new(&format!("{top_level}/{pattern}"))
+                .unwrap()
+                .matches_path(path)
+        };
+
+        if self.excludes.iter().any(matches) {
+            return Ok(true);
+        }
+        let suspicious = match path.extension() {
+            Some(ext) => ext == "c" || ext == "a",
+            _ => false,
+        };
+
+        let debian_dir_pattern = Pattern::new(&format!("{top_level}/debian/*")).unwrap();
+        if debian_dir_pattern.matches_path(path) {
+            return Err(format!(
+                "Suspicious file or directory, should probably be excluded: {:?}",
+                path
+            ));
+        }
+
+        if suspicious {
+            if self.includes.iter().any(matches) {
+                debcargo_info!("Suspicious file, on whitelist so ignored: {:?}", path);
+                Ok(false)
+            } else if testing_ignore_debpolv() {
+                debcargo_warn!("Suspicious file, ignoring as per override: {:?}", path);
+                Ok(false)
+            } else {
+                Err(format!(
+                    "Suspicious file, should probably be excluded: {:?}",
+                    path
+                ))
+            }
+        } else {
+            Ok(false)
+        }
+    }
+
+    pub fn extract_crate(&mut self, path: &Path) -> Result<bool> {
+        let mut archive = Archive::new(GzDecoder::new(self.crate_file.file()));
+        let tempdir = tempfile::Builder::new()
+            .prefix("debcargo")
+            .tempdir_in(".")?;
+        let mut source_modified = false;
+        let mut last_mtime = 0;
+        let mut err = vec![];
+
+        for entry in archive.entries()? {
+            let mut entry = entry?;
+            match self.filter_path(&(entry.path()?)) {
+                Err(e) => err.push(e),
+                Ok(r) => {
+                    if r {
+                        source_modified = true;
+                        continue;
+                    }
+                }
+            }
+
+            if !entry.unpack_in(tempdir.path())? {
+                debcargo_bail!("Crate contained path traversals via '..'");
+            }
+
+            if let Ok(mtime) = entry.header().mtime() {
+                if mtime > last_mtime {
+                    last_mtime = mtime;
+                }
+            }
+        }
+        if !err.is_empty() {
+            for e in err {
+                debcargo_warn!("{}", e);
+            }
+            debcargo_bail!(
+                "Suspicious files detected, aborting. Ask on #debian-rust if you are stuck."
+            )
+        }
+
+        let entries = tempdir.path().read_dir()?.collect::<io::Result<Vec<_>>>()?;
+        if entries.len() != 1 || !entries[0].file_type()?.is_dir() {
+            let pkgid = self.package_id();
+            debcargo_bail!(
+                "{}-{}.crate did not unpack to a single top-level directory",
+                pkgid.name(),
+                pkgid.version()
+            );
+        }
+
+        if let Err(e) = fs::rename(entries[0].path(), path) {
+            return Err(Error::from(e).context(format!(
+                concat!(
+                    "Could not create source directory {0}\n",
+                    "To regenerate, move or remove {0}"
+                ),
+                path.display()
+            )));
+        }
+
+        // Ensure that Cargo.toml is in standard form, e.g. does not contain
+        // path dependencies, so can be built standalone (see #4030).
+        let toml_path = path.join("Cargo.toml");
+        let mut actual_toml = String::new();
+        fs::File::open(&toml_path)?.read_to_string(&mut actual_toml)?;
+
+        if !actual_toml.contains("AUTOMATICALLY GENERATED BY CARGO") {
+            // This logic should only fire for old crates, and that's what the
+            // if-conditional is supposed to check; modern versions of cargo
+            // already do this before uploading the crate, and we shouldn't need
+            // to handle it specially.
+            log::debug!("Cargo.toml not canonicalized..");
+            let orig_toml = actual_toml.clone();
+
+            // Some old uncanonicalized Cargo.toml files contain invalid relative references to
+            // license or readme files that newer cargo doesn't accept anymore. attempt to monkey
+            // patch them if possible
+            let mut check_reference = |name, value: Option<&str>| {
+                if let Some(referenced_path) = value {
+                    let full_referenced_path = path.join(referenced_path);
+                    if !full_referenced_path.exists() {
+                        debcargo_warn!(
+                            "Cargo.toml references non-existing license_file path: {:?}",
+                            full_referenced_path
+                        );
+                        if let Some((_prefix, file)) = referenced_path.rsplit_once("/") {
+                            if path.join(file).exists() {
+                                debcargo_info!("Replacing reference with '{}'", file);
+                                actual_toml = actual_toml.replace(referenced_path, file);
+                            } else {
+                                debcargo_info!("Removing reference");
+                                actual_toml = actual_toml
+                                    .replace(&format!("{name} = \"{referenced_path}\""), "");
+                            }
+                        } else {
+                            debcargo_info!("Removing reference");
+                            actual_toml =
+                                actual_toml.replace(&format!("{name} = \"{referenced_path}\""), "");
+                        }
+                        return true;
+                    }
+                }
+
+                false
+            };
+
+            if check_reference("license-file", self.metadata().license_file.as_deref())
+                || check_reference("readme", self.metadata().readme.as_deref())
+            {
+                fs::write(&toml_path, actual_toml.as_bytes())?;
+            }
+            let updated = self.replace_manifest(&toml_path.canonicalize()?)?;
+
+            let ws = Workspace::new(&toml_path.canonicalize()?, &updated.context)?;
+            let opts = PackageOpts {
+                gctx: &updated.context,
+                list: false,
+                check_metadata: false,
+                allow_dirty: true,
+                verify: false,
+                jobs: None,
+                keep_going: false,
+                to_package: Packages::Default,
+                targets: Vec::new(),
+                cli_features: CliFeatures::new_all(true),
+                reg_or_index: None,
+            };
+            let files = ops::package(&ws, &opts)?;
+            let file = files
+                .first()
+                .ok_or_else(|| format_err!("No canonicalized archives found.."))?;
+            let mut archive = Archive::new(GzDecoder::new(file.file()));
+
+            for entry in archive.entries()? {
+                let mut entry = entry?;
+                let entry_path = entry.path()?;
+                let components = entry_path.iter();
+                if components.clone().count() == 2
+                    && components.last() == Some(OsStr::new("Cargo.toml"))
+                {
+                    entry.unpack(&toml_path)?;
+                    break;
+                }
+            }
+            fs::write(path.join("Cargo.toml.orig"), orig_toml.as_bytes())?;
+            fs::remove_dir_all(path.join("target"))?;
+            source_modified = true;
+            // avoid lintian errors about package-contains-ancient-file
+            // TODO: do we want to do this for unmodified tarballs? it would
+            // force us to modify them, but otherwise we get that ugly warning
+            let last_mtime = FileTime::from_unix_time(last_mtime as i64, 0);
+            set_file_times(toml_path, last_mtime, last_mtime)?;
+            debcargo_info!("Cargo.toml manually canonicalized!");
+        }
+        Ok(source_modified)
+    }
+}
+
+/// Collect information about the dependency structure of features and
+/// their external crate dependencies, in a simple output format.
+pub fn all_dependencies_and_features(manifest: &Manifest) -> CrateDepInfo {
+    use cargo::core::dependency::DepKind;
+
+    let mut deps_by_name: BTreeMap<&str, Vec<&Dependency>> = BTreeMap::new();
+    for dep in manifest.dependencies() {
+        // we treat build-dependencies also as dependencies in Debian
+        if dep.kind() != DepKind::Development {
+            let s = dep.name_in_toml().as_str();
+            deps_by_name.entry(s).or_default().push(dep);
+        }
+    }
+    let deps_by_name = deps_by_name;
+
+    let mut features_with_deps = BTreeMap::new();
+
+    // calculate dependencies of this crate's features
+    for (feature, deps) in manifest.summary().features() {
+        let mut feature_deps: Vec<&'static str> = vec![];
+        let mut other_deps: Vec<Dependency> = Vec::new();
+        for dep in deps {
+            use self::FeatureValue::*;
+            match dep {
+                // another feature is a dependency
+                Feature(dep_feature) => {
+                    feature_deps.push(InternedString::new(dep_feature).as_str())
+                }
+                // another package is a dependency
+                Dep { dep_name } => {
+                    // unwrap is ok, valid Cargo.toml files must have this
+                    for &dep in deps_by_name.get(dep_name.as_str()).unwrap() {
+                        other_deps.push(dep.clone());
+                    }
+                }
+                // another package is a dependency
+                DepFeature {
+                    dep_name,
+                    dep_feature,
+                    ..
+                } => {
+                    match deps_by_name.get(dep_name.as_str()) {
+                        // unwrap is ok, valid Cargo.toml files must have this
+                        Some(dd) => {
+                            for &dep in dd {
+                                let mut dep = dep.clone();
+                                let mut features: Vec<InternedString> =
+                                    vec![InternedString::new(dep_feature)];
+                                features.extend(dep.features());
+                                dep.set_features(features);
+                                dep.set_default_features(false);
+                                other_deps.push(dep);
+                            }
+                        }
+                        None => {
+                            let mut expected = false;
+                            for dep in manifest.dependencies() {
+                                if dep.kind() == DepKind::Development {
+                                    let s = dep.name_in_toml().as_str();
+                                    if s == dep_name.as_str() {
+                                        expected = true;
+                                    }
+                                }
+                            }
+                            if expected {
+                                debcargo_warn!(
+                                    "Ignoring \"{}\" feature \"{}\" as it depends on a \
+                                     dev-dependency \"{}\"",
+                                    manifest.package_id(),
+                                    feature,
+                                    dep_name
+                                );
+                            } else {
+                                panic!(
+                                    "failed to account for dependency \"{}\" of \"{}\" feature \"{}\"",
+                                    dep_name, manifest.package_id(), feature
+                                );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if feature_deps.is_empty() {
+            // everything depends on bare library
+            feature_deps.push("");
+        }
+        features_with_deps.insert(feature.as_str(), (feature_deps, other_deps));
+    }
+
+    // calculate required dependencies for implicit no-default-features
+    let mut deps_required: Vec<Dependency> = Vec::new();
+    for deps in deps_by_name.values() {
+        for &dep in deps {
+            if !dep.is_optional() {
+                deps_required.push(dep.clone())
+            }
+        }
+    }
+
+    // implicit no-default-features
+    features_with_deps.insert("", (vec![], deps_required));
+
+    // implicit default feature
+    if !features_with_deps.contains_key("default") {
+        features_with_deps.insert("default", (vec![""], vec![]));
+    }
+
+    features_with_deps
+}
+
+/// Calculate all feature-dependencies and external-dependencies of a given
+/// feature, using the information previously generated by
+/// `all_dependencies_and_features`.
+pub fn transitive_deps<'a>(
+    features_with_deps: &'a CrateDepInfo,
+    feature: &str,
+) -> Result<(Vec<&'a str>, Vec<Dependency>)> {
+    let mut all_features = Vec::new();
+    let mut all_deps = Vec::new();
+    if let Some((ff, dd)) = features_with_deps.get(feature) {
+        all_features.extend(ff.clone());
+        all_deps.extend(dd.clone());
+        for f in ff {
+            let (ff1, dd1) = transitive_deps(features_with_deps, f)?;
+            all_features.extend(ff1);
+            all_deps.extend(dd1);
+        }
+    } else {
+        log::trace!("{features_with_deps:?}");
+        debcargo_bail!(
+            "requested feature '{}' not found in resolved map of features+dependencies",
+            feature
+        );
+    }
+    Ok((all_features, all_deps))
+}
diff --git a/src/deb_dependencies.rs b/src/deb_dependencies.rs
new file mode 100644 (file)
index 0000000..b682836
--- /dev/null
@@ -0,0 +1,83 @@
+use std::collections::BTreeSet;
+use std::path::PathBuf;
+
+use cargo::core::EitherManifest;
+use cargo::core::SourceId;
+use cargo::util::toml::read_manifest;
+use cargo::GlobalContext;
+
+use anyhow::Error;
+use clap::Parser;
+
+use crate::crates::all_dependencies_and_features;
+use crate::crates::transitive_deps;
+use crate::debian::deb_deps;
+use crate::debian::toolchain_deps;
+
+#[derive(Debug, Clone, Parser)]
+pub struct DebDependenciesArgs {
+    /// Cargo.toml for generating dependencies
+    cargo_toml: PathBuf,
+    /// Features to include in dependencies
+    #[clap(long)]
+    features: Vec<String>,
+    /// Include all features in dependencies
+    #[clap(long)]
+    all_features: bool,
+    /// Do not include default feature in dependencies
+    #[clap(long="no-default-features", action=clap::ArgAction::SetFalse)]
+    uses_default_features: bool,
+    /// Allow prerelease versions of dependencies
+    #[clap(long)]
+    allow_prerelease_deps: bool,
+}
+
+pub fn deb_dependencies(
+    args: DebDependenciesArgs,
+) -> Result<(Vec<String>, BTreeSet<String>), Error> {
+    let cargo_toml = args.cargo_toml.canonicalize()?;
+    let EitherManifest::Real(manifest) = read_manifest(
+        &cargo_toml,
+        SourceId::for_path(cargo_toml.parent().unwrap())?,
+        &GlobalContext::default()?,
+    )?
+    else {
+        debcargo_bail!("Manifest lacks project and package sections")
+    };
+
+    let deps_and_features = all_dependencies_and_features(&manifest);
+
+    let features = {
+        let mut features: std::collections::HashSet<_> = if args.all_features {
+            deps_and_features.keys().copied().collect()
+        } else {
+            args.features
+                .iter()
+                .flat_map(|s| s.split_whitespace())
+                .flat_map(|s| s.split(','))
+                .filter(|s| !s.is_empty())
+                .collect()
+        };
+
+        if args.uses_default_features {
+            features.insert("default");
+        }
+
+        features.insert("");
+
+        features
+    };
+    let dependencies = {
+        let mut dependencies = BTreeSet::<String>::new();
+        for feature in features.iter() {
+            if !deps_and_features.contains_key(feature) {
+                debcargo_bail!("Unknown feature: {}", feature);
+            }
+            let (_, feature_deps) = transitive_deps(&deps_and_features, feature)?;
+            dependencies.extend(deb_deps(args.allow_prerelease_deps, &feature_deps)?);
+        }
+        dependencies
+    };
+    let toolchain_deps = toolchain_deps(&manifest.rust_version().map(|x| x.to_string()));
+    Ok((toolchain_deps, dependencies))
+}
diff --git a/src/debian/changelog.rs b/src/debian/changelog.rs
new file mode 100644 (file)
index 0000000..fb1d771
--- /dev/null
@@ -0,0 +1,185 @@
+use anyhow;
+use chrono::{DateTime, FixedOffset, Local, TimeZone};
+use regex::Regex;
+
+use std::fmt;
+use std::str;
+
+pub const DEFAULT_DIST: &str = "UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO";
+pub const COMMENT_TEAM_UPLOAD: &str = "  * Team upload.";
+
+pub struct ChangelogEntry {
+    pub source: String,
+    pub version: String,
+    pub distribution: String,
+    pub options: String,
+    pub maintainer: String,
+    pub date: DateTime<FixedOffset>,
+    pub items: Vec<String>,
+}
+
+pub fn local_now() -> DateTime<FixedOffset> {
+    let now = Local::now();
+    let offset = now
+        .timezone()
+        .offset_from_local_datetime(&now.naive_local())
+        .unwrap();
+    now.with_timezone(&offset)
+}
+
+impl fmt::Display for ChangelogEntry {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "{} ({}) {}; {}\n",
+            self.source, self.version, self.distribution, self.options
+        )?;
+
+        for entry in self.items.iter() {
+            writeln!(f, "{}", entry)?;
+        }
+
+        writeln!(f, "\n -- {}  {}", self.maintainer, self.date.to_rfc2822())
+    }
+}
+
+fn line_is_blank(s: &str) -> bool {
+    s.chars().all(char::is_whitespace)
+}
+
+impl str::FromStr for ChangelogEntry {
+    type Err = anyhow::Error;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let mut lines = s.lines().collect::<Vec<_>>();
+        // see https://manpages.debian.org/testing/dpkg-dev/deb-changelog.5.en.html
+        // regexes adapted from /usr/share/perl5/Dpkg/Changelog/Entry/Debian.pm
+
+        let firstline = lines[0];
+        let re1 =
+            Regex::new(r"(?i)^(\w[-+0-9a-z.]*) \(([^\(\) \t]+)\)((?:\s+[-+0-9a-z.]+)+);(.*?)\s*$")?;
+        let matches1 = re1.captures(firstline).unwrap();
+        let mut i = 1;
+        while line_is_blank(lines[i]) {
+            i += 1;
+        }
+        lines = lines.split_off(i);
+
+        while line_is_blank(lines.last().unwrap()) {
+            lines.pop();
+        }
+        let lastline = lines.pop().unwrap();
+        while line_is_blank(lines.last().unwrap()) {
+            lines.pop();
+        }
+        let re2 = Regex::new(r"^ \-\- ((?:.*) <(?:.*)>)  ?(\w.*\S)\s*$")?;
+        let matches2 = re2.captures(lastline).unwrap();
+
+        Ok(Self::new(
+            matches1[1].to_string(),
+            matches1[2].to_string(),
+            matches1[3].to_string(),
+            matches1[4].to_string(),
+            matches2[1].to_string(),
+            DateTime::parse_from_rfc2822(&matches2[2])?,
+            lines.iter().map(|s| s.to_string()).collect(),
+        ))
+    }
+}
+
+impl ChangelogEntry {
+    pub fn new(
+        source: String,
+        version: String,
+        distribution: String,
+        options: String,
+        maintainer: String,
+        date: DateTime<FixedOffset>,
+        items: Vec<String>,
+    ) -> Self {
+        ChangelogEntry {
+            source,
+            version,
+            distribution,
+            options,
+            maintainer,
+            date,
+            items,
+        }
+    }
+
+    pub fn maintainer_name(self: &ChangelogEntry) -> String {
+        let re = Regex::new(r"^\s*(\S.*\S)\s*<.*>\s*$").unwrap();
+        let matches = re.captures(&self.maintainer).unwrap();
+        matches[1].to_string()
+    }
+
+    pub fn version_parts(self: &ChangelogEntry) -> (String, String) {
+        let re = Regex::new(r"^(.*)-([^-]*)$").unwrap();
+        let matches = re.captures(&self.version).unwrap();
+        (matches[1].to_string(), matches[2].to_string())
+    }
+
+    pub fn deb_version_suffix(self: &ChangelogEntry) -> String {
+        let re = Regex::new(r".*-([^-]*)$").unwrap();
+        re.captures(&self.version).unwrap()[1].to_string()
+    }
+
+    pub fn deb_version_suffix_bump(self: &ChangelogEntry) -> String {
+        let suf = self.deb_version_suffix();
+        let re = Regex::new(r"^((?:.*\D)?)(\d*)$").unwrap();
+        let matches = re.captures(&suf).unwrap();
+        if matches[2].is_empty() {
+            format!("{}.1", &matches[1])
+        } else {
+            format!(
+                "{}{}",
+                &matches[1],
+                (matches[2].parse::<u64>().unwrap() + 1)
+            )
+        }
+    }
+}
+
+pub struct ChangelogIterator<'a> {
+    input: &'a [u8],
+    index: usize,
+}
+
+impl<'a> ChangelogIterator<'a> {
+    pub fn from(input: &'a str) -> ChangelogIterator<'a> {
+        ChangelogIterator {
+            input: input.as_bytes(),
+            index: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for ChangelogIterator<'a> {
+    type Item = &'a str;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a str> {
+        let slice = &self.input[self.index..];
+        if slice.is_empty() {
+            return None;
+        }
+        let mut result = slice;
+        // ghetto parser; also hack around the fact rust's str doesn't
+        // support proper indexing, boo
+        for (i, c) in slice.iter().enumerate() {
+            if *c != b'\n' {
+                continue;
+            }
+            if i < (slice.len() - 1) && (slice[i + 1] as char).is_whitespace() {
+                continue;
+            }
+            self.index += i + 1;
+            result = &slice[..=i];
+            break;
+        }
+        Some(str::from_utf8(result).unwrap())
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/changelog/tests.rs b/src/debian/changelog/tests.rs
new file mode 100644 (file)
index 0000000..b244366
--- /dev/null
@@ -0,0 +1,242 @@
+use crate::debian::changelog::{ChangelogEntry, ChangelogIterator};
+use chrono::{FixedOffset, TimeZone};
+use std::str::FromStr;
+
+/// changelog for rsa selected because 0.9.2-2 appears twice
+const CHANGELOG_RSA: &str = r"rust-rsa (0.9.7-1) unstable; urgency=medium
+
+  * Team upload.
+  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5
+  * Drop unneeded dependency adjustments
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 05 Dec 2024 11:08:36 -0500
+
+rust-rsa (0.9.6-1) unstable; urgency=medium
+
+  * Package rsa 0.9.6 from crates.io using debcargo 2.7.0. Closes: ##1073127
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Wed, 25 Sep 2024 14:06:55 +0100
+
+rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+rust-rsa (0.9.2-1) unstable; urgency=medium
+
+  * Package rsa 0.9.2 from crates.io using debcargo 2.6.0
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Mon, 18 Sep 2023 23:08:13 +0100
+
+";
+
+#[test]
+fn test_changelog_iterator() {
+    let mut iter = ChangelogIterator::from(CHANGELOG_RSA);
+
+    let section = r"rust-rsa (0.9.7-1) unstable; urgency=medium
+
+  * Team upload.
+  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5
+  * Drop unneeded dependency adjustments
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 05 Dec 2024 11:08:36 -0500
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.6-1) unstable; urgency=medium
+
+  * Package rsa 0.9.6 from crates.io using debcargo 2.7.0. Closes: ##1073127
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Wed, 25 Sep 2024 14:06:55 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.2-2) unstable; urgency=medium
+
+  * Add patch pkcs8: fix compatibility with pkcs8.
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Tue, 19 Sep 2023 21:27:07 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+    let section = r"rust-rsa (0.9.2-1) unstable; urgency=medium
+
+  * Package rsa 0.9.2 from crates.io using debcargo 2.6.0
+
+ -- Jelmer Vernooij <jelmer@debian.org>  Mon, 18 Sep 2023 23:08:13 +0100
+
+";
+    assert_eq!(section, iter.next().unwrap());
+
+    // assert that the iterator ends
+    assert_eq!(None, iter.next());
+}
+
+#[test]
+fn test_from_string() {
+    let mut iter = ChangelogIterator::from(CHANGELOG_RSA);
+
+    let instance = ChangelogEntry::from_str(iter.next().unwrap()).unwrap();
+
+    assert_eq!("rust-rsa", instance.source);
+    assert_eq!(
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        instance.date
+    );
+    assert_eq!(
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned()
+        ],
+        instance.items
+    );
+    assert_eq!("0.9.7-1", instance.version);
+    assert_eq!(
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>",
+        instance.maintainer
+    );
+    assert_eq!(" unstable", instance.distribution);
+    assert_eq!(" urgency=medium", instance.options);
+}
+
+#[test]
+fn test_changelog_entry_display() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    let expected = r"rust-rsa (0.9.7-1) unstable; urgency=medium
+
+  * Team upload.
+  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5
+  * Drop unneeded dependency adjustments
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Thu, 5 Dec 2024 11:08:36 -0500
+";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+#[test]
+fn test_changelog_entry_maintainer_name() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!("Daniel Kahn Gillmor", instance.maintainer_name());
+}
+
+#[test]
+fn test_changelog_entry_version_parts() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!(
+        ("0.9.7".to_owned(), "1".to_owned()),
+        instance.version_parts()
+    );
+}
+
+#[test]
+fn test_changelog_entry_deb_version_suffix() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!("1", instance.deb_version_suffix());
+}
+
+#[test]
+fn test_changelog_entry_deb_version_suffix_bump() {
+    let instance = ChangelogEntry::new(
+        "rust-rsa".to_owned(),
+        "0.9.7-1".to_owned(),
+        "unstable".to_owned(),
+        "urgency=medium".to_owned(),
+        "Daniel Kahn Gillmor <dkg@fifthhorseman.net>".to_owned(),
+        FixedOffset::west_opt(5 * 3600)
+            .unwrap()
+            .with_ymd_and_hms(2024, 12, 05, 11, 08, 36)
+            .unwrap(),
+        vec![
+            "  * Team upload.".to_owned(),
+            "  * Package rsa 0.9.7 from crates.io using debcargo 2.7.5".to_owned(),
+            "  * Drop unneeded dependency adjustments".to_owned(),
+        ],
+    );
+
+    assert_eq!("2", instance.deb_version_suffix_bump());
+}
diff --git a/src/debian/control.rs b/src/debian/control.rs
new file mode 100644 (file)
index 0000000..7947992
--- /dev/null
@@ -0,0 +1,711 @@
+#[cfg(not(test))]
+use std::env::{self, VarError};
+use std::fmt::{self, Write};
+
+#[cfg(not(test))]
+use anyhow::{format_err, Error};
+use semver::Version;
+use textwrap::fill;
+
+use crate::config::{self, Config, PackageKey};
+use crate::errors::*;
+
+#[derive(Default, Debug)]
+pub struct BuildDeps {
+    pub(crate) build_depends: Vec<String>,
+    pub(crate) build_depends_indep: Vec<String>,
+    pub(crate) build_depends_arch: Vec<String>,
+}
+
+pub struct Source {
+    name: String,
+    section: String,
+    priority: String,
+    maintainer: String,
+    uploaders: Vec<String>,
+    standards: String,
+    build_deps: BuildDeps,
+    vcs_git: String,
+    vcs_browser: String,
+    homepage: String,
+    crate_name: String,
+    requires_root: Option<String>,
+}
+
+pub struct Package {
+    name: String,
+    arch: String,
+    multi_arch: Option<String>,
+    section: Option<String>,
+    depends: Vec<String>,
+    recommends: Vec<String>,
+    suggests: Vec<String>,
+    provides: Vec<String>,
+    breaks: Vec<String>,
+    replaces: Vec<String>,
+    conflicts: Vec<String>,
+    summary: Description,
+    description: Description,
+    extra_lines: Vec<String>,
+}
+
+pub struct Description {
+    pub prefix: String,
+    pub suffix: String,
+}
+
+impl Description {
+    pub fn new(prefix: String, suffix: String) -> Self {
+        Self { prefix, suffix }
+    }
+}
+
+pub struct PkgTest {
+    name: String,
+    crate_name: String,
+    feature: String,
+    version: String,
+    extra_test_args: Vec<String>,
+    depends: Vec<String>,
+    extra_restricts: Vec<String>,
+    architecture: Vec<String>,
+}
+
+impl fmt::Display for Source {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Source: {}", self.name)?;
+        writeln!(f, "Section: {}", self.section)?;
+        writeln!(f, "Priority: {}", self.priority)?;
+        if !self.build_deps.build_depends.is_empty() {
+            writeln!(
+                f,
+                "Build-Depends: {}",
+                self.build_deps.build_depends.join(",\n ")
+            )?;
+        }
+        if !self.build_deps.build_depends_arch.is_empty() {
+            writeln!(
+                f,
+                "Build-Depends-Arch: {}",
+                self.build_deps.build_depends_arch.join(",\n ")
+            )?;
+        }
+        if !self.build_deps.build_depends_indep.is_empty() {
+            writeln!(
+                f,
+                "Build-Depends-Indep: {}",
+                self.build_deps.build_depends_indep.join(",\n ")
+            )?;
+        }
+        writeln!(f, "Maintainer: {}", self.maintainer)?;
+        if !self.uploaders.is_empty() {
+            writeln!(f, "Uploaders:\n {}", self.uploaders.join(",\n "))?;
+        }
+        writeln!(f, "Standards-Version: {}", self.standards)?;
+        writeln!(f, "Vcs-Git: {}", self.vcs_git)?;
+        writeln!(f, "Vcs-Browser: {}", self.vcs_browser)?;
+
+        if !self.homepage.is_empty() {
+            writeln!(f, "Homepage: {}", self.homepage)?;
+        }
+
+        // We used to set this conditionally, however it's best to do it
+        // unconditionally as some crates' names have a number suffix e.g.
+        // "utf-8". Without setting X-Cargo-Crate, we cannot distinguish:
+        //   a) "utf" crate at version 8 with semver_suffix = true
+        //   b) "utf-8" crate at version latest with semver_suffix = false.
+        // dh-cargo assumes (a) which is wrong for the "utf-8" crate
+        writeln!(f, "X-Cargo-Crate: {}", self.crate_name)?;
+        if let Some(ref rrr) = self.requires_root {
+            writeln!(f, "Rules-Requires-Root: {}", rrr)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl fmt::Display for Package {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Package: {}", self.name)?;
+        writeln!(f, "Architecture: {}", self.arch)?;
+        if let Some(ref multi_arch) = self.multi_arch {
+            writeln!(f, "Multi-Arch: {}", multi_arch)?;
+        }
+
+        if let Some(section) = &self.section {
+            writeln!(f, "Section: {}", section)?;
+        }
+
+        if !self.depends.is_empty() {
+            writeln!(f, "Depends:\n {}", self.depends.join(",\n "))?;
+        }
+        if !self.recommends.is_empty() {
+            writeln!(f, "Recommends:\n {}", self.recommends.join(",\n "))?;
+        }
+        if !self.suggests.is_empty() {
+            writeln!(f, "Suggests:\n {}", self.suggests.join(",\n "))?;
+        }
+        if !self.provides.is_empty() {
+            writeln!(f, "Provides:\n {}", self.provides.join(",\n "))?;
+        }
+        if !self.replaces.is_empty() {
+            writeln!(f, "Replaces:\n {}", self.replaces.join(",\n "))?;
+        }
+        if !self.breaks.is_empty() {
+            writeln!(f, "Breaks:\n {}", self.breaks.join(",\n "))?;
+        }
+        if !self.conflicts.is_empty() {
+            writeln!(f, "Conflicts:\n {}", self.conflicts.join(",\n "))?;
+        }
+
+        for line in &self.extra_lines {
+            writeln!(f, "{}", line)?;
+        }
+
+        self.write_description(f)
+    }
+}
+
+impl fmt::Display for PkgTest {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let extra_args = if self.extra_test_args.is_empty() {
+            "".into()
+        } else {
+            format!(" {}", self.extra_test_args.join(" "))
+        };
+        writeln!(
+            f,
+            "Test-Command: /usr/share/cargo/bin/cargo-auto-test {} {} --all-targets{}",
+            self.crate_name, self.version, extra_args,
+        )?;
+        writeln!(f, "Features: test-name={}:{}", &self.name, &self.feature)?;
+        // TODO: drop the below workaround when rust-lang/cargo#5133 is fixed.
+        // The downside of our present work-around is that more dependencies
+        // must be installed, which makes it harder to actually run the tests
+        let cargo_bug_fixed = false;
+        let default_deps = if cargo_bug_fixed { &self.name } else { "@" };
+
+        let depends = if self.depends.is_empty() {
+            "".into()
+        } else {
+            format!(", {}", self.depends.join(", "))
+        };
+        writeln!(f, "Depends: dh-cargo (>= 31){}, {}", depends, default_deps)?;
+
+        let restricts = if self.extra_restricts.is_empty() {
+            "".into()
+        } else {
+            format!(", {}", self.extra_restricts.join(", "))
+        };
+        writeln!(
+            f,
+            "Restrictions: allow-stderr, skip-not-installable{}",
+            restricts,
+        )?;
+        if !self.architecture.is_empty() {
+            writeln!(f, "Architecture: {}", self.architecture.join(" "))?;
+        }
+        Ok(())
+    }
+}
+
+impl Source {
+    pub fn pkg_prefix() -> &'static str {
+        if config::testing_ruzt() {
+            // avoid accidentally installing official packages during tests
+            "ruzt"
+        } else {
+            "rust"
+        }
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        basename: &str,
+        name_suffix: Option<&str>,
+        crate_name: &str,
+        home: &str,
+        lib: bool,
+        maintainer: String,
+        uploaders: Vec<String>,
+        build_deps: BuildDeps,
+        requires_root: Option<String>,
+    ) -> Result<Source> {
+        let pkgbase = match name_suffix {
+            None => basename.to_string(),
+            Some(suf) => format!("{}{}", basename, suf),
+        };
+        let section = if lib {
+            "rust"
+        } else {
+            "FIXME-IN-THE-SOURCE-SECTION"
+        };
+        let priority = "optional".to_string();
+        let vcs_browser = format!(
+            "https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/{}",
+            pkgbase
+        );
+        let vcs_git = format!(
+            "https://salsa.debian.org/rust-team/debcargo-conf.git [src/{}]",
+            pkgbase
+        );
+        Ok(Source {
+            name: dsc_name(&pkgbase),
+            section: section.to_string(),
+            priority,
+            maintainer,
+            uploaders,
+            standards: "4.7.2".to_string(),
+            build_deps,
+            vcs_git,
+            vcs_browser,
+            homepage: home.to_string(),
+            crate_name: crate_name.to_string(),
+            requires_root,
+        })
+    }
+
+    pub fn name(&self) -> &str {
+        &self.name
+    }
+
+    pub fn apply_overrides(&mut self, config: &Config) {
+        if let Some(section) = config.section() {
+            self.section = section.to_string();
+        }
+
+        if let Some(policy) = config.policy_version() {
+            self.standards = policy.to_string();
+        }
+
+        self.build_deps.build_depends.extend(
+            config
+                .build_depends()
+                .into_iter()
+                .flatten()
+                .map(String::to_string),
+        );
+        self.build_deps.build_depends_arch.extend(
+            config
+                .build_depends_arch()
+                .into_iter()
+                .flatten()
+                .map(String::to_string),
+        );
+        self.build_deps.build_depends_indep.extend(
+            config
+                .build_depends_indep()
+                .into_iter()
+                .flatten()
+                .map(String::to_string),
+        );
+        let bdeps_ex = config
+            .build_depends_excludes()
+            .map(Vec::as_slice)
+            .unwrap_or(&[]);
+        self.build_deps
+            .build_depends
+            .retain(|x| !bdeps_ex.contains(x));
+
+        self.build_deps
+            .build_depends_arch
+            .retain(|x| !bdeps_ex.contains(x));
+
+        self.build_deps
+            .build_depends_indep
+            .retain(|x| !bdeps_ex.contains(x));
+
+        if let Some(homepage) = config.homepage() {
+            self.homepage = homepage.to_string();
+        }
+
+        if let Some(vcs_git) = config.vcs_git() {
+            self.vcs_git = vcs_git.to_string();
+        }
+
+        if let Some(vcs_browser) = config.vcs_browser() {
+            self.vcs_browser = vcs_browser.to_string();
+        }
+
+    }
+}
+
+impl Package {
+    pub fn pkg_prefix() -> &'static str {
+        if config::testing_ruzt() {
+            // avoid accidentally installing official packages during tests
+            "libruzt"
+        } else {
+            "librust"
+        }
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        basename: &str,
+        name_suffix: Option<&str>,
+        version: &Version,
+        summary: Description,
+        description: Description,
+        feature: Option<&str>,
+        f_deps: Vec<&str>,
+        o_deps: Vec<String>,
+        f_provides: Vec<&str>,
+        f_recommends: Vec<&str>,
+        f_suggests: Vec<&str>,
+    ) -> Result<Package> {
+        let pkgbase = match name_suffix {
+            None => basename.to_string(),
+            Some(suf) => format!("{}{}", basename, suf),
+        };
+        let deb_feature2 = &|p: &str, f: &str| {
+            format!(
+                "{} (= ${{binary:Version}})",
+                match f {
+                    "" => deb_name(p),
+                    _ => deb_feature_name(p, f),
+                }
+            )
+        };
+        let deb_feature = &|f: &str| deb_feature2(&pkgbase, f);
+
+        let filter_provides = &|x: Vec<&str>| {
+            x.into_iter()
+                .filter(|f| !f_provides.contains(f))
+                .map(deb_feature)
+                .collect()
+        };
+        let (recommends, suggests) = match feature {
+            Some(_) => (vec![], vec![]),
+            None => (filter_provides(f_recommends), filter_provides(f_suggests)),
+        };
+
+        // Provides for all possible versions, see:
+        // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=901827#35
+        // https://wiki.debian.org/Teams/RustPackaging/Policy#Package_provides
+        let mut provides = vec![];
+        let version_suffixes = [
+            "".to_string(),
+            format!("-{}", version.major),
+            format!("-{}.{}", version.major, version.minor),
+            format!("-{}.{}.{}", version.major, version.minor, version.patch),
+        ];
+        for suffix in version_suffixes.iter() {
+            // don't provide unversioned variants in semver-suffix packages
+            if name_suffix.is_some() && suffix.is_empty() {
+                continue;
+            };
+
+            let p = format!("{}{}", basename, suffix);
+            provides.push(deb_feature2(&p, feature.unwrap_or("")));
+            provides.extend(f_provides.iter().map(|f| deb_feature2(&p, f)));
+        }
+        let provides_self = deb_feature(feature.unwrap_or(""));
+        // rust dropped Vec::remove_item for annoying reasons, the below is
+        // an unofficialy recommended replacement from the RFC #40062
+        let i = provides.iter().position(|x| *x == *provides_self);
+        i.map(|i| provides.remove(i));
+
+        let mut depends = vec!["${misc:Depends}".to_string()];
+        if feature.is_some() && !f_deps.contains(&"") {
+            // in dh-cargo we symlink /usr/share/doc/{$feature => $main} pkg
+            // so we always need this direct dependency, even if the feature
+            // only indirectly depends on the bare library via another
+            depends.push(deb_feature(""));
+        }
+        depends.extend(f_deps.into_iter().map(deb_feature));
+        depends.extend(o_deps);
+        let mut breaks = vec![];
+        let mut replaces = vec![];
+        if name_suffix.is_some() && feature.is_none() {
+            // B+R needs to be set on "real" package, not virtual ones
+            // constrain by "next" version, so that it is possible to install a newer,
+            // non-suffixed package at the same time
+            let mut next_version = version.clone();
+            next_version.patch += 1;
+            breaks.push(format!("{} (<< {}~)", deb_name(basename), next_version));
+            replaces.push(format!("{} (<< {}~)", deb_name(basename), next_version));
+        }
+        let conflicts = vec![];
+
+        Ok(Package {
+            name: match feature {
+                None => deb_name(&pkgbase),
+                Some(f) => deb_feature_name(&pkgbase, f),
+            },
+            arch: "any".to_string(),
+            // This is the best but not ideal option for us.
+            //
+            // Currently Debian M-A spec has a deficiency where a package X that
+            // build-depends on a (M-A:foreign+arch:all) package that itself
+            // depends on an arch:any package Z, will pick up the BUILD_ARCH of
+            // package Z instead of the HOST_ARCH. This is because we currently
+            // have no way of telling dpkg to use HOST_ARCH when checking that the
+            // dependencies of Y are satisfied, which is done at install-time
+            // without any knowledge that we're about to do a cross-compile. It
+            // is also problematic to tell dpkg to "accept any arch" because of
+            // the presence of non-M-A:same packages in the archive, that are not
+            // co-installable - different arches of Z might be depended-upon by
+            // two conflicting chains. (dpkg has so far chosen not to add an
+            // exception for the case where package Z is M-A:same co-installable).
+            //
+            // The recommended work-around for now from the dpkg developers is to
+            // make our packages arch:any M-A:same even though this results in
+            // duplicate packages in the Debian archive. For very large crates we
+            // will eventually want to make debcargo generate -data packages that
+            // are arch:all and have the arch:any -dev packages depend on it.
+            multi_arch: Some("same".to_string()),
+            section: None,
+            depends,
+            recommends,
+            suggests,
+            provides,
+            breaks,
+            replaces,
+            conflicts,
+            summary,
+            description,
+            extra_lines: vec![],
+        })
+    }
+
+    pub fn new_bin(
+        basename: &str,
+        name_suffix: Option<&str>,
+        section: Option<&str>,
+        summary: Description,
+        description: Description,
+    ) -> Self {
+        let (name, mut provides) = match name_suffix {
+            None => (basename.to_string(), vec![]),
+            Some(suf) => (
+                format!("{}{}", basename, suf),
+                vec![format!("{} (= ${{binary:Version}})", basename)],
+            ),
+        };
+        provides.push("${cargo:Provides}".to_string());
+        Package {
+            name,
+            arch: "any".to_string(),
+            multi_arch: None,
+            section: section.map(|s| s.to_string()),
+            depends: vec![
+                "${misc:Depends}".to_string(),
+                "${shlibs:Depends}".to_string(),
+                "${cargo:Depends}".to_string(),
+            ],
+            recommends: vec!["${cargo:Recommends}".to_string()],
+            suggests: vec!["${cargo:Suggests}".to_string()],
+            provides,
+            breaks: vec![],
+            replaces: vec![],
+            conflicts: vec![],
+            summary,
+            description,
+            extra_lines: vec![
+                "Built-Using: ${cargo:Built-Using}".to_string(),
+                "Static-Built-Using: ${cargo:Static-Built-Using}".to_string(),
+            ],
+        }
+    }
+
+    pub fn name(&self) -> &str {
+        self.name.as_str()
+    }
+
+    fn write_description(&self, out: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(out, "Description: {}", &self.summary)?;
+        let description = format!("{}", &self.description);
+        for line in fill(description.trim(), 79).lines() {
+            let line = line.trim_end();
+            if line.is_empty() {
+                writeln!(out, " .")?;
+            } else if line.starts_with("- ") {
+                writeln!(out, "  {}", line)?;
+            } else {
+                writeln!(out, " {}", line)?;
+            }
+        }
+        Ok(())
+    }
+
+    #[allow(clippy::result_unit_err)]
+    pub fn summary_check_len(&self) -> std::result::Result<(), ()> {
+        if self.summary.prefix.len() <= 80 {
+            Ok(())
+        } else {
+            Err(())
+        }
+    }
+
+    pub fn apply_overrides(&mut self, config: &Config, key: PackageKey, f_provides: Vec<&str>) {
+        if let Some(section) = config.package_section(key) {
+            self.section = Some(section.to_string());
+        }
+        self.summary
+            .apply_overrides(&config.summary, config.package_summary(key));
+        self.description
+            .apply_overrides(&config.description, config.package_description(key));
+
+        self.depends.extend(config::package_field_for_feature(
+            &|x| config.package_depends(x),
+            key,
+            &f_provides,
+        ));
+        self.recommends.extend(config::package_field_for_feature(
+            &|x| config.package_recommends(x),
+            key,
+            &f_provides,
+        ));
+        self.suggests.extend(config::package_field_for_feature(
+            &|x| config.package_suggests(x),
+            key,
+            &f_provides,
+        ));
+        self.provides.extend(config::package_field_for_feature(
+            &|x| config.package_provides(x),
+            key,
+            &f_provides,
+        ));
+        self.breaks.extend(config::package_field_for_feature(
+            &|x| config.package_breaks(x),
+            key,
+            &f_provides,
+        ));
+        self.replaces.extend(config::package_field_for_feature(
+            &|x| config.package_replaces(x),
+            key,
+            &f_provides,
+        ));
+        self.conflicts.extend(config::package_field_for_feature(
+            &|x| config.package_conflicts(x),
+            key,
+            &f_provides,
+        ));
+        self.extra_lines.extend(
+            config
+                .package_extra_lines(key)
+                .into_iter()
+                .flatten()
+                .map(|s| s.to_string()),
+        );
+        if let Some(architecture) = config.package_architecture(key) {
+            self.arch = architecture.join(" ");
+        }
+        if let Some(multi_arch) = config.package_multi_arch(key) {
+            self.multi_arch = Some(multi_arch.to_owned());
+        }
+    }
+}
+
+impl Description {
+    fn apply_overrides(&mut self, global: &Option<String>, per_package: Option<&str>) {
+        if let Some(per_package) = per_package {
+            self.prefix = per_package.to_string();
+            self.suffix = "".to_string();
+        } else if let Some(global) = &global {
+            self.prefix = global.into();
+        }
+    }
+}
+impl fmt::Display for Description {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}{}", &self.prefix, self.suffix)
+    }
+}
+
+impl PkgTest {
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        name: &str,
+        crate_name: &str,
+        feature: &str,
+        version: &str,
+        extra_test_args: Vec<&str>,
+        depends: &[String],
+        extra_restricts: Vec<&str>,
+        architecture: &[&str],
+    ) -> Result<PkgTest> {
+        Ok(PkgTest {
+            name: name.to_string(),
+            crate_name: crate_name.to_string(),
+            feature: feature.to_string(),
+            version: version.to_string(),
+            extra_test_args: extra_test_args.iter().map(|x| x.to_string()).collect(),
+            depends: depends.to_vec(),
+            extra_restricts: extra_restricts.iter().map(|x| x.to_string()).collect(),
+            architecture: architecture.iter().map(|x| x.to_string()).collect(),
+        })
+    }
+}
+
+/// Translates a semver into a Debian-format upstream version.
+/// Omits the build metadata, and uses a ~ before the prerelease version so it
+/// compares earlier than the subsequent release.
+pub fn deb_upstream_version(v: &Version) -> String {
+    let mut s = format!("{}.{}.{}", v.major, v.minor, v.patch);
+    if !v.pre.is_empty() {
+        write!(s, "~{}", v.pre.as_str()).unwrap();
+    }
+    s
+}
+
+pub fn base_deb_name(crate_name: &str) -> String {
+    crate_name.replace('_', "-").to_lowercase()
+}
+
+pub fn dsc_name(name: &str) -> String {
+    format!("{}-{}", Source::pkg_prefix(), base_deb_name(name))
+}
+
+pub fn deb_name(name: &str) -> String {
+    format!("{}-{}-dev", Package::pkg_prefix(), base_deb_name(name))
+}
+
+pub fn deb_feature_name(name: &str, feature: &str) -> String {
+    format!(
+        "{}-{}+{}-dev",
+        Package::pkg_prefix(),
+        base_deb_name(name),
+        base_deb_name(feature)
+    )
+}
+
+/// Retrieve one of a series of environment variables, and provide a friendly error message for
+/// non-UTF-8 values.
+#[cfg(not(test))]
+fn get_envs(keys: &[&str]) -> Result<Option<String>> {
+    for key in keys {
+        match env::var(key) {
+            Ok(val) => {
+                return Ok(Some(val));
+            }
+            Err(e @ VarError::NotUnicode(_)) => {
+                return Err(Error::from(e)
+                    .context(format!("Environment variable ${} not valid UTF-8", key)));
+            }
+            Err(VarError::NotPresent) => {}
+        }
+    }
+    Ok(None)
+}
+
+#[cfg(test)]
+pub(crate) fn get_deb_author() -> Result<String> {
+    Ok("Debcargo Test <debcargo@example.com>".to_string())
+}
+
+/// Determine a name and email address from environment variables.
+#[cfg(not(test))]
+pub fn get_deb_author() -> Result<String> {
+    let name = get_envs(&["DEBFULLNAME", "NAME"])?.ok_or_else(|| {
+        format_err!("Unable to determine your name; please set $DEBFULLNAME or $NAME")
+    })?;
+    let email = get_envs(&["DEBEMAIL", "EMAIL"])?.ok_or_else(|| {
+        format_err!("Unable to determine your email; please set $DEBEMAIL or $EMAIL")
+    })?;
+    Ok(format!("{} <{}>", name, email))
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/control/tests.rs b/src/debian/control/tests.rs
new file mode 100644 (file)
index 0000000..ea94bf8
--- /dev/null
@@ -0,0 +1,411 @@
+use super::{
+    base_deb_name, deb_feature_name, deb_name, deb_upstream_version, dsc_name, Description,
+    Package, PkgTest, Source,
+};
+use crate::{
+    config::{Config, SourceOverride},
+    debian::BuildDeps,
+};
+use semver::{Prerelease, Version};
+
+#[test]
+fn source_to_string() {
+    let instance = Source::new(
+        "rsa",
+        None,
+        "rsa",
+        "https://github.com/RustCrypto/RSA",
+        true,
+        "Jelmer Vernooij <jelmer@debian.org>".to_owned(),
+        vec!["Jelmer Vernooij <jelmer@debian.org>".to_owned()],
+        BuildDeps::default(),
+        None,
+    )
+    .unwrap();
+
+    let expected = "Source: rust-rsa\nSection: rust\nPriority: optional\nMaintainer: Jelmer Vernooij <jelmer@debian.org>\nUploaders:\n Jelmer Vernooij <jelmer@debian.org>\nStandards-Version: 4.7.2\nVcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/rsa]\nVcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/rsa\nHomepage: https://github.com/RustCrypto/RSA\nX-Cargo-Crate: rsa\n";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+fn empty_source_overrides() -> SourceOverride {
+    SourceOverride::new(
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some("".to_owned()),
+        Some(vec!["rust-digest".to_owned()]),
+        Some(vec!["".to_owned()]),
+        Some(vec!["".to_owned()]),
+        Some(vec!["rust-const-oid".to_owned()]),
+        Some(false),
+    )
+}
+
+#[test]
+fn test_description_display() {
+    let instance = Description::new("prefix".to_owned(), "suffix".to_owned());
+
+    assert_eq!("prefixsuffix", instance.to_string())
+}
+
+#[test]
+fn test_apply_overrides() {
+    let mut instance = Source::new(
+        "rsa",
+        None,
+        "rsa",
+        "https://github.com/RustCrypto/RSA",
+        true,
+        "Jelmer Vernooij <jelmer@debian.org>".to_owned(),
+        vec!["Jelmer Vernooij <jelmer@debian.org>".to_owned()],
+        BuildDeps {
+            build_depends: vec![
+                "rust-const-oid".to_owned(),
+                "rust-num-bigint-dig".to_owned(),
+            ],
+            ..BuildDeps::default()
+        },
+        Some("no".to_owned()),
+    )
+    .unwrap();
+
+    assert_eq!("rust", instance.section);
+    assert_eq!(
+        vec!["rust-const-oid", "rust-num-bigint-dig"],
+        instance.build_deps.build_depends
+    );
+    assert_eq!("https://github.com/RustCrypto/RSA", instance.homepage);
+    assert_eq!(
+        "https://salsa.debian.org/rust-team/debcargo-conf.git [src/rsa]",
+        instance.vcs_git
+    );
+    assert_eq!(
+        "https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/rsa",
+        instance.vcs_browser
+    );
+
+    let mut config = Config::default();
+    config.source = Some(empty_source_overrides());
+    instance.apply_overrides(&config);
+
+    assert_eq!("", instance.section);
+    assert_eq!(
+        vec!["rust-num-bigint-dig", "rust-digest"],
+        instance.build_deps.build_depends
+    );
+    assert_eq!("", instance.homepage);
+    assert_eq!("", instance.vcs_git);
+    assert_eq!("", instance.vcs_browser);
+}
+
+#[test]
+fn test_package_new() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let version: &Version = &Version {
+        major: 0,
+        minor: 9,
+        patch: 7,
+        pre: Default::default(),
+        build: Default::default(),
+    };
+    let summary: Description = Description::new("summary_pre".to_owned(), "summary_suf".to_owned());
+    let description: Description =
+        Description::new("description_pre".to_owned(), "description_suf".to_owned());
+    let feature: Option<&str> = None;
+    let f_deps: Vec<&str> = vec![];
+    let o_deps: Vec<String> = vec![];
+    let f_provides: Vec<&str> = vec![];
+    let f_recommends: Vec<&str> = vec![];
+    let f_suggests: Vec<&str> = vec![];
+    let instance = Package::new(
+        basename,
+        name_suffix,
+        version,
+        summary,
+        description,
+        feature,
+        f_deps,
+        o_deps,
+        f_provides,
+        f_recommends,
+        f_suggests,
+    );
+
+    assert!(instance.is_ok());
+    let instance = instance.unwrap();
+    assert_eq!("any", instance.arch);
+    assert_eq!(Some("same".to_string()), instance.multi_arch);
+    assert_eq!(None, instance.section);
+    assert_eq!(vec!["${misc:Depends}"], instance.depends);
+    assert_eq!(Vec::<String>::new(), instance.recommends);
+    assert_eq!(Vec::<String>::new(), instance.suggests);
+    assert_eq!(
+        vec![
+            "librust-rsa-0-dev (= ${binary:Version})",
+            "librust-rsa-0.9-dev (= ${binary:Version})",
+            "librust-rsa-0.9.7-dev (= ${binary:Version})"
+        ],
+        instance.provides
+    );
+    assert_eq!("summary_pre", instance.summary.prefix);
+    assert_eq!("summary_suf", instance.summary.suffix);
+    assert_eq!("description_pre", instance.description.prefix);
+    assert_eq!("description_suf", instance.description.suffix);
+    assert_eq!(Vec::<String>::new(), instance.extra_lines);
+}
+
+#[test]
+fn test_package_new_bin() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    let summary: Description = Description::new("summary_pre".to_owned(), "summary_suf".to_owned());
+    let description: Description =
+        Description::new("description_pre".to_owned(), "description_suf".to_owned());
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    assert_eq!("any", instance.arch);
+    assert_eq!(None, instance.multi_arch);
+    assert_eq!(Some("rust".to_owned()), instance.section);
+    assert_eq!(
+        vec!["${misc:Depends}", "${shlibs:Depends}", "${cargo:Depends}"],
+        instance.depends
+    );
+    assert_eq!(vec!["${cargo:Recommends}"], instance.recommends);
+    assert_eq!(vec!["${cargo:Suggests}"], instance.suggests);
+    assert_eq!(vec!["${cargo:Provides}"], instance.provides);
+    assert_eq!("summary_pre", instance.summary.prefix);
+    assert_eq!("summary_suf", instance.summary.suffix);
+    assert_eq!("description_pre", instance.description.prefix);
+    assert_eq!("description_suf", instance.description.suffix);
+    assert_eq!(
+        vec![
+            "Built-Using: ${cargo:Built-Using}",
+            "Static-Built-Using: ${cargo:Static-Built-Using}"
+        ],
+        instance.extra_lines
+    );
+}
+
+#[test]
+fn test_package_display() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    let summary: Description = Description::new("".to_owned(), "".to_owned());
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    let expected = "Package: rsa\nArchitecture: any\nSection: rust\nDepends:\n ${misc:Depends},\n ${shlibs:Depends},\n ${cargo:Depends}\nRecommends:\n ${cargo:Recommends}\nSuggests:\n ${cargo:Suggests}\nProvides:\n ${cargo:Provides}\nBuilt-Using: ${cargo:Built-Using}\nStatic-Built-Using: ${cargo:Static-Built-Using}\nDescription: \n description_start\n .\n empty lines\n .\n description_stop\n";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+#[test]
+fn test_package_display_arch() {
+    let basename: &str = "tiny-dfr";
+    let name_suffix: Option<&str> = None;
+    let section = Some("utils");
+    let summary: Description = Description::new("".to_owned(), "".to_owned());
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let mut instance = Package::new_bin(basename, name_suffix, section, summary, description);
+    instance.arch = "arm64 amd64".to_string();
+
+    let expected = "Package: tiny-dfr\nArchitecture: arm64 amd64\nSection: utils\nDepends:\n ${misc:Depends},\n ${shlibs:Depends},\n ${cargo:Depends}\nRecommends:\n ${cargo:Recommends}\nSuggests:\n ${cargo:Suggests}\nProvides:\n ${cargo:Provides}\nBuilt-Using: ${cargo:Built-Using}\nStatic-Built-Using: ${cargo:Static-Built-Using}\nDescription: \n description_start\n .\n empty lines\n .\n description_stop\n";
+
+    assert_eq!(expected, instance.to_string());
+}
+
+#[test]
+fn test_package_summary_check_len() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    let summary: Description = Description::new("".to_owned(), "".to_owned());
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    assert!(instance.summary_check_len().is_ok());
+}
+
+#[test]
+fn test_package_summary_check_len_err() {
+    let basename: &str = "rsa";
+    let name_suffix: Option<&str> = None;
+    let section = Some("rust");
+    // 81 character long line
+    let summary: Description = Description::new(
+        "123456789012345678901234567890123456789012345678901234567890123456789012345678901"
+            .to_owned(),
+        "".to_owned(),
+    );
+    let description: Description = Description::new(
+        "description_start\n\nempty lines\n\ndescription_stop".to_owned(),
+        "".to_owned(),
+    );
+    let instance = Package::new_bin(basename, name_suffix, section, summary, description);
+
+    assert!(instance.summary_check_len().is_err());
+}
+
+#[test]
+fn test_pkg_test_new() {
+    let name = "rsa";
+    let crate_name = "rsa";
+    let feature = "pem";
+    let version = "0.9.7";
+    let extra_test_args: Vec<&str> = vec![];
+    let depends: Vec<String> = vec![];
+    let extra_restricts: Vec<&str> = vec![];
+    let architecture: Vec<&str> = vec![];
+    let instance = PkgTest::new(
+        name,
+        crate_name,
+        feature,
+        version,
+        extra_test_args,
+        &depends,
+        extra_restricts,
+        &architecture,
+    );
+
+    assert!(instance.is_ok());
+    let instance = instance.unwrap();
+    assert_eq!("rsa", instance.name);
+    assert_eq!("rsa", instance.crate_name);
+    assert_eq!("pem", instance.feature);
+    assert_eq!("0.9.7", instance.version);
+    assert_eq!(Vec::<String>::new(), instance.extra_test_args);
+    assert_eq!(Vec::<String>::new(), instance.depends);
+    assert_eq!(Vec::<String>::new(), instance.extra_restricts);
+    assert_eq!(Vec::<String>::new(), instance.architecture);
+}
+
+#[test]
+fn test_deb_upstream_version_without_pre() {
+    let version = Version {
+        major: 0,
+        minor: 9,
+        patch: 7,
+        pre: Default::default(),
+        build: Default::default(),
+    };
+
+    let result = deb_upstream_version(&version);
+
+    let expected = "0.9.7";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_deb_upstream_version_with_pre() {
+    let version = Version {
+        major: 0,
+        minor: 9,
+        patch: 7,
+        pre: Prerelease::new("alpha").unwrap(),
+        build: Default::default(),
+    };
+
+    let result = deb_upstream_version(&version);
+
+    let expected = "0.9.7~alpha";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_base_deb_name() {
+    let result = base_deb_name("derive_more");
+
+    let expected = "derive-more";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_dsc_name() {
+    let result = dsc_name("derive_more");
+
+    let expected = "rust-derive-more";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_deb_name() {
+    let result = deb_name("derive_more");
+
+    let expected = "librust-derive-more-dev";
+
+    assert_eq!(expected, result);
+}
+
+#[test]
+fn test_deb_feature_name() {
+    let result = deb_feature_name("derive_more", "add");
+
+    let expected = "librust-derive-more+add-dev";
+
+    assert_eq!(expected, result);
+}
+
+struct PkgTestFmtData<'a> {
+    feature: &'a str,
+    extra_test_args: Vec<&'a str>,
+    depends: Vec<String>,
+    extra_restricts: Vec<&'a str>,
+    architecture: &'a [&'a str],
+}
+
+#[test]
+fn pkgtest_fmt_has_no_extra_whitespace() {
+    let checks = vec![
+        PkgTestFmtData {
+            feature: "",
+            extra_test_args: Vec::new(),
+            depends: Vec::new(),
+            extra_restricts: Vec::new(),
+            architecture: &[],
+        },
+        PkgTestFmtData {
+            feature: "X",
+            extra_test_args: vec!["--no-default-features", "--features X"],
+            depends: vec!["libfoo-dev".into(), "bar".into()],
+            extra_restricts: vec!["flaky"],
+            architecture: &["!riscv64"],
+        },
+    ];
+
+    for check in checks {
+        let pkgtest = PkgTest::new(
+            "librust-crate-dev",
+            "crate",
+            check.feature,
+            "1.0",
+            check.extra_test_args,
+            &check.depends,
+            check.extra_restricts,
+            check.architecture,
+        )
+        .unwrap();
+
+        for ln in pkgtest.to_string().lines() {
+            let trimmed = ln.trim_end();
+            assert_eq!(trimmed, ln);
+        }
+    }
+}
diff --git a/src/debian/copyright.rs b/src/debian/copyright.rs
new file mode 100644 (file)
index 0000000..d48cc84
--- /dev/null
@@ -0,0 +1,442 @@
+use cargo::core::manifest;
+use chrono::{DateTime, Datelike};
+use git2::Repository;
+use regex;
+use tempfile;
+use textwrap::fill;
+use walkdir;
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::env;
+use std::fmt;
+use std::fs;
+use std::io::{BufRead, BufReader, Read};
+use std::path::Path;
+
+use crate::errors::*;
+
+const DEB_COPYRIGHT_FORMAT: &str = "\
+     https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/";
+
+macro_rules! format_para {
+    ($fmt: expr, $text:expr) => {{
+        for line in $text.lines() {
+            let line = line.trim_end();
+            if line.is_empty() {
+                writeln!($fmt, " .")?;
+            } else {
+                writeln!($fmt, " {}", line)?;
+            }
+        }
+        write!($fmt, "")
+    }};
+}
+
+struct UpstreamInfo {
+    name: String,
+    contacts: Vec<String>,
+    source: String,
+}
+
+#[derive(Clone)]
+pub struct Files {
+    files: String,
+    copyright: Vec<String>,
+    license: String,
+    comment: String,
+}
+
+#[derive(Clone)]
+struct License {
+    name: String,
+    text: String,
+}
+
+pub struct DebCopyright {
+    format: String,
+    upstream: UpstreamInfo,
+    files: Vec<Files>,
+    licenses: Vec<License>,
+}
+
+impl fmt::Display for DebCopyright {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Format: {}", self.format)?;
+        write!(f, "{}", self.upstream)?;
+
+        for file in &self.files {
+            write!(f, "\n{}", file)?;
+        }
+
+        for license in &self.licenses {
+            write!(f, "\n{}", license)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl DebCopyright {
+    fn new(u: UpstreamInfo, f: &[Files], l: &[License]) -> DebCopyright {
+        DebCopyright {
+            format: DEB_COPYRIGHT_FORMAT.to_string(),
+            upstream: u,
+            files: f.to_vec(),
+            licenses: l.to_vec(),
+        }
+    }
+}
+
+impl fmt::Display for UpstreamInfo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Upstream-Name: {}", self.name)?;
+        write!(f, "Upstream-Contact:")?;
+        if self.contacts.len() > 1 {
+            writeln!(f)?;
+        }
+        for contact in &self.contacts {
+            writeln!(f, " {}", contact)?;
+        }
+        if !self.source.is_empty() {
+            writeln!(f, "Source: {}", self.source)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl UpstreamInfo {
+    fn new(name: String, authors: &[String], repo: &str) -> UpstreamInfo {
+        assert!(!authors.is_empty());
+        UpstreamInfo {
+            name,
+            contacts: authors.to_vec(),
+            source: repo.to_string(),
+        }
+    }
+}
+
+impl fmt::Display for Files {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Files: {}", self.files)?;
+        write!(f, "Copyright:")?;
+        if self.copyright.len() > 1 {
+            writeln!(f)?;
+        }
+        for copyright in &self.copyright {
+            writeln!(f, " {}", copyright)?;
+        }
+        writeln!(f, "License: {}", self.license)?;
+        if !self.comment.is_empty() {
+            writeln!(f, "Comment:")?;
+            format_para!(f, &self.comment)?;
+        }
+        Ok(())
+    }
+}
+
+impl Files {
+    pub fn new<T: ToString>(name: &str, notice: &[T], license: &str, comment: &str) -> Files {
+        assert!(!notice.is_empty());
+        Files {
+            files: name.to_string(),
+            copyright: notice.iter().map(|s| s.to_string()).collect(),
+            license: license.to_string(),
+            comment: comment.to_string(),
+        }
+    }
+
+    pub fn files(&self) -> &str {
+        &self.files
+    }
+
+    pub fn license(&self) -> &str {
+        &self.license
+    }
+}
+
+impl fmt::Display for License {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "License: {}", self.name)?;
+        format_para!(f, &self.text)?;
+        Ok(())
+    }
+}
+
+impl License {
+    fn new(name: String, text: String) -> License {
+        License { name, text }
+    }
+}
+
+macro_rules! default_files {
+    ($file:expr, $notice:expr) => {{
+        let comment = concat!(
+            "FIXME (overlay): These notices are extracted from files. Please ",
+            "review them before uploading to the archive."
+        );
+        Files::new(
+            $file,
+            $notice,
+            "UNKNOWN-LICENSE; FIXME (overlay)",
+            &fill(comment, 79),
+        )
+    }};
+}
+
+fn gen_files(debsrcdir: &Path) -> Result<Vec<Files>> {
+    let mut copyright_notices = BTreeMap::new();
+
+    let copyright_notice_re =
+        regex::Regex::new(r"(?:[Cc]opyright|©)(?:\s|[©:,()Cc<])*\b(\d{4}\b.*)$")?;
+
+    // Get current working directory and move inside the extracted source of
+    // crate. This is necessary in order to capture correct path for files in
+    // debian/copyright.
+    let current_dir = env::current_dir()?;
+    env::set_current_dir(debsrcdir)?;
+
+    // Here we specifically use "." to avoid absolute paths. If we use
+    // current_dir then we end up having absolute path from user home directory,
+    // which again messes debian/copyright.
+    // Use of . creates paths in format ./src/, so we strip the leading "./"
+    for entry in walkdir::WalkDir::new(".").sort_by(|a, b| a.file_name().cmp(b.file_name())) {
+        let entry = entry?;
+        if entry.file_type().is_file() {
+            let copyright_file = entry
+                .path()
+                .strip_prefix("./")?
+                .to_str()
+                .unwrap()
+                .to_string();
+            let file = fs::File::open(entry.path())?;
+            let reader = BufReader::new(file);
+            for line in reader.lines() {
+                if let Ok(line) = line {
+                    if let Some(m) = copyright_notice_re.captures(&line) {
+                        let m = m.get(1).unwrap();
+                        let start = m.start();
+                        let end = m.end();
+                        let notice = line[start..end]
+                            .trim_end()
+                            .trim_end_matches(". See the COPYRIGHT")
+                            .to_string();
+                        if !copyright_notices.contains_key(&copyright_file) {
+                            copyright_notices.insert(copyright_file.clone(), vec![]);
+                        }
+                        copyright_notices
+                            .get_mut(&copyright_file)
+                            .unwrap()
+                            .push(notice);
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    // Restore back to original working directory as we can continue without
+    // problems.
+    env::set_current_dir(current_dir.as_path())?;
+
+    let mut notices: Vec<Files> = Vec::new();
+    for (filename, notice) in &copyright_notices {
+        notices.push(default_files!(filename, notice));
+    }
+
+    Ok(notices)
+}
+
+fn get_licenses(license: &str) -> Result<Vec<License>> {
+    let mut licenses = BTreeMap::new();
+    let sep = regex::Regex::new(r"(?i:(\s(or|and)\s|/))")?;
+    let known_licenses = vec![
+        ("agpl-3.0", include_str!("licenses/AGPL-3.0")),
+        ("apache-2.0", include_str!("licenses/Apache-2.0")),
+        ("bsd-2-clause", include_str!("licenses/BSD-2-Clause")),
+        ("bsd-3-clause", include_str!("licenses/BSD-3-Clause")),
+        ("cc0-1.0", include_str!("licenses/CC0-1.0")),
+        ("gpl-2.0", include_str!("licenses/GPL-2.0")),
+        ("gpl-3.0", include_str!("licenses/GPL-3.0")),
+        ("isc", include_str!("licenses/ISC")),
+        ("lgpl-2.0", include_str!("licenses/LGPL-2.0")),
+        ("lgpl-2.1", include_str!("licenses/LGPL-2.1")),
+        ("lgpl-3.0", include_str!("licenses/LGPL-3.0")),
+        ("mit", include_str!("licenses/MIT")),
+        ("mitnfa", include_str!("licenses/MITNFA")),
+        ("mpl-1.1", include_str!("licenses/MPL-1.1")),
+        ("mpl-2.0", include_str!("licenses/MPL-2.0")),
+        ("unlicense", include_str!("licenses/Unlicense")),
+        ("zlib", include_str!("licenses/Zlib")),
+    ]
+    .into_iter()
+    .collect::<BTreeMap<_, _>>();
+
+    let lses: Vec<&str> = sep.split(license).filter(|s| !s.is_empty()).collect();
+    for ls in lses {
+        let lname = ls
+            .trim()
+            .to_lowercase()
+            .trim_end_matches('+')
+            .trim_end_matches("-or-later")
+            .to_string();
+        let text = match known_licenses.get(lname.as_str()) {
+            Some(s) => s.to_string(),
+            None => "FIXME (overlay): Unrecognized crate license, please find the \
+                     full license text in the rest of the crate source code and \
+                     copy-paste it here"
+                .to_string(),
+        };
+        licenses.insert(ls.trim().to_string(), text);
+    }
+
+    let mut lblocks: Vec<License> = Vec::new();
+    if !licenses.is_empty() {
+        for (l, t) in licenses {
+            lblocks.push(License::new(l, t));
+        }
+    }
+
+    Ok(lblocks)
+}
+
+fn copyright_fromgit(repo_url: &str) -> Result<String> {
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(".")?;
+    let repo = Repository::clone(repo_url, tempdir.path())?;
+
+    let mut revwalker = repo.revwalk()?;
+    revwalker.push_head()?;
+
+    // Get the latest and first commit id. This is a bit ugly
+    let latest_id = revwalker.next().unwrap()?;
+    let first_id = revwalker.last().unwrap()?; // revwalker ends here is consumed by last
+
+    let first_commit = repo.find_commit(first_id)?;
+    let latest_commit = repo.find_commit(latest_id)?;
+
+    let first_year = &DateTime::from_timestamp(first_commit.time().seconds(), 0)
+        .ok_or(anyhow::Error::msg("lo"))?
+        .year();
+
+    let latest_year = &DateTime::from_timestamp(latest_commit.time().seconds(), 0)
+        .ok_or(anyhow::Error::msg("lo"))?
+        .year();
+
+    let notice = match first_year.cmp(latest_year) {
+        Ordering::Equal => format!("{}", first_year),
+        _ => format!("{}-{},", first_year, latest_year),
+    };
+
+    Ok(notice)
+}
+
+pub fn debian_copyright(
+    srcdir: &Path,
+    manifest: &manifest::Manifest,
+    manifest_path: &Path,
+    maintainer: &str,
+    uploaders: &[&str],
+    year_range: (i32, i32),
+    guess_harder: bool,
+) -> Result<DebCopyright> {
+    let meta = manifest.metadata().clone();
+    let repository = meta.repository.unwrap_or_default();
+
+    // The Authors field is optional according to
+    // https://rust-lang.github.io/rfcs/3052-optional-authors-field.html
+    // and crates.io publishes crates without the field already.
+    let unknown_authors = vec!["FIXME (overlay) UNKNOWN-AUTHORS".to_string()];
+    let authors = if meta.authors.is_empty() {
+        &unknown_authors
+    } else {
+        &meta.authors
+    };
+
+    let upstream = UpstreamInfo::new(manifest.name().to_string(), authors, &repository);
+
+    let mut licenses: Vec<License> = Vec::new();
+    let mut crate_license: String = "".to_string();
+
+    if let Some(ref license_file_name) = meta.license_file {
+        let license_file = manifest_path.with_file_name(license_file_name);
+        let mut text = Vec::new();
+        licenses.reserve(1);
+        let stext = match fs::File::open(license_file).and_then(|mut f| f.read_to_end(&mut text)) {
+            Ok(_) => String::from_utf8(text)?,
+            Err(e) => {
+                format!("Failed to read license from {license_file_name} - {e:?}")
+            }
+        };
+        licenses.push(License::new(
+            "UNKNOWN-LICENSE; FIXME (overlay)".to_string(),
+            stext,
+        ));
+    } else if let Some(ref license) = meta.license {
+        licenses = get_licenses(license)?;
+        crate_license = license
+            .trim()
+            .replace('/', " or ")
+            .replace(" OR ", " or ")
+            .replace(" AND ", " and ");
+    } else {
+        debcargo_bail!("Crate has no license or license_file");
+    }
+
+    let mut files = gen_files(srcdir)?;
+
+    let (y0, y1) = year_range;
+    let years = if y0 == y1 {
+        format!("{}", y0)
+    } else {
+        format!("{}-{}", y0, y1)
+    };
+    let mut deb_notice = vec![format!("{} {}", years, maintainer)];
+    deb_notice.extend(uploaders.iter().map(|s| format!("{} {}", years, s)));
+    files.push(Files::new("debian/*", &deb_notice, &crate_license, ""));
+
+    // Insert catch all block as the first block of copyright file. Capture
+    // copyright notice from git log of the upstream repository.
+    let years = if guess_harder && !repository.is_empty() {
+        match copyright_fromgit(&repository) {
+            Ok(x) => x,
+            Err(e) => {
+                debcargo_warn!(
+                    "Failed to generate d/copyright from git repository {}: {}\n",
+                    repository,
+                    e
+                );
+                "FIXME (overlay) UNKNOWN-YEARS".to_string()
+            }
+        }
+    } else {
+        "FIXME (overlay) UNKNOWN-YEARS".to_string()
+    };
+    let notice = match meta.authors.len() {
+        0 => vec![format!("FIXME (overlay) UNKNOWN-AUTHORS {}", years)],
+        1 => vec![format!("{} {}", years, &meta.authors[0])],
+        _ => meta
+            .authors
+            .iter()
+            .map(|s| format!("{} {}", years, s))
+            .collect(),
+    };
+    let comment = concat!(
+        "FIXME (overlay): Since upstream copyright years are not available ",
+        "in Cargo.toml, they were extracted from the upstream Git ",
+        "repository. This may not be correct information so you should ",
+        "review and fix this before uploading to the archive."
+    );
+    files.insert(
+        0,
+        Files::new("*", notice.as_slice(), &crate_license, &fill(comment, 79)),
+    );
+
+    Ok(DebCopyright::new(upstream, &files, &licenses))
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/copyright/tests.rs b/src/debian/copyright/tests.rs
new file mode 100644 (file)
index 0000000..d7d60ba
--- /dev/null
@@ -0,0 +1,109 @@
+use super::{debian_copyright, get_licenses};
+
+use std::{io::Write, path::Path};
+
+use cargo::{
+    core::{package::Package, EitherManifest, SourceId},
+    GlobalContext,
+};
+use toml::toml;
+
+#[test]
+fn check_get_licenses() {
+    let test_data: &[(&str, &[(&str, bool)])] = &[
+        ("AGPL-3.0", &[("AGPL-3.0", true)]),
+        ("AcmeCorp-1.0", &[("AcmeCorp-1.0", false)]),
+        ("AGPL-3.0-or-later", &[("AGPL-3.0-or-later", true)]),
+        ("Apache-2.0/MIT", &[("Apache-2.0", true), ("MIT", true)]),
+        ("Apache-2.0 or MIT", &[("Apache-2.0", true), ("MIT", true)]),
+        (
+            "FooBar-1.0 AND MIT",
+            &[("FooBar-1.0", false), ("MIT", true)],
+        ),
+    ];
+    for (name, expected) in test_data {
+        let licenses = get_licenses(name).expect("getting licenses failed");
+        let found: Vec<_> = licenses
+            .iter()
+            .map(|l| (l.name.as_str(), !l.text.starts_with("FIXME")))
+            .collect();
+        assert_eq!(&found[..], &expected[..]);
+    }
+}
+
+#[test]
+fn check_debian_copyright_authors() {
+    let checks = vec![
+        (
+            vec![],
+            vec!["FIXME (overlay) UNKNOWN-AUTHORS FIXME (overlay) UNKNOWN-YEARS"],
+        ),
+        (
+            vec!["Jordan Doe"],
+            vec!["FIXME (overlay) UNKNOWN-YEARS Jordan Doe"],
+        ),
+        (
+            vec!["Jordan Doe", "Jane Doe"],
+            vec![
+                "FIXME (overlay) UNKNOWN-YEARS Jordan Doe",
+                "FIXME (overlay) UNKNOWN-YEARS Jane Doe",
+            ],
+        ),
+    ];
+
+    for (input, expected_output) in checks.into_iter() {
+        let package = build_package_with_authors(input);
+        let srcdir = tempfile::tempdir().unwrap();
+        let copyright = debian_copyright(
+            srcdir.path(),
+            package.manifest(),
+            package.manifest_path(),
+            "Jordan Doe",
+            &[],
+            (2000, 2020),
+            false,
+        )
+        .unwrap();
+        let mut generated = false;
+        for file in &copyright.files {
+            if file.files == "*" {
+                assert_eq!(file.copyright, expected_output);
+                generated = true;
+            }
+        }
+        assert!(generated);
+    }
+}
+
+fn build_package_with_authors(authors: Vec<&str>) -> Package {
+    let authors: Vec<String> = authors.into_iter().map(|s| s.to_string()).collect();
+    let toml = toml! {
+        [package]
+        name = "mypackage"
+        version = "1.2.3"
+        authors = authors
+        license = "AGPLv3"
+    };
+    let tmp_dir = tempfile::tempdir().unwrap();
+    let manifest_path = tmp_dir.path().join("Cargo.toml");
+    let mut manifest_file = std::fs::File::create(&manifest_path).unwrap();
+    manifest_file
+        .write_all(toml::to_string(&toml).unwrap().as_bytes())
+        .unwrap();
+
+    let src_dir = tmp_dir.path().join("src");
+    std::fs::create_dir(&src_dir).unwrap();
+    std::fs::File::create(src_dir.join("lib.rs")).unwrap();
+    #[cfg(unix)]
+    let package_root = Path::new("/");
+    #[cfg(windows)]
+    let package_root = Path::new("C:\\");
+    let source_id = SourceId::for_path(package_root).unwrap();
+    let context = GlobalContext::default().unwrap();
+    let manifest = cargo::util::toml::read_manifest(&manifest_path, source_id, &context).unwrap();
+    if let EitherManifest::Real(manifest) = manifest {
+        Package::new(manifest, Path::new("/path/to/manifest"))
+    } else {
+        unimplemented!();
+    }
+}
diff --git a/src/debian/dependency.rs b/src/debian/dependency.rs
new file mode 100644 (file)
index 0000000..d97df13
--- /dev/null
@@ -0,0 +1,346 @@
+use cargo::core::Dependency;
+use itertools::Itertools;
+
+use std::cmp;
+use std::fmt;
+
+use crate::config::testing_ignore_debpolv;
+use crate::debian::{self, control::base_deb_name, Package};
+use crate::errors::*;
+
+#[derive(Eq, Clone)]
+#[allow(clippy::upper_case_acronyms)]
+enum V {
+    M(u64),
+    MM(u64, u64),
+    MMP(u64, u64, u64),
+}
+
+impl V {
+    fn new(p: &semver::Comparator) -> Result<Self> {
+        use self::V::*;
+        let mmp = match (p.minor, p.patch) {
+            (None, None) => M(p.major),
+            (Some(minor), None) => MM(p.major, minor),
+            (Some(minor), Some(patch)) => MMP(p.major, minor, patch),
+            (None, Some(_)) => debcargo_bail!("semver had patch without minor"),
+        };
+        Ok(mmp)
+    }
+
+    fn inclast(&self) -> V {
+        use self::V::*;
+        match *self {
+            M(major) => M(major + 1),
+            MM(major, minor) => MM(major, minor + 1),
+            MMP(major, minor, patch) => MMP(major, minor, patch + 1),
+        }
+    }
+
+    fn mmp(&self) -> (u64, u64, u64) {
+        use self::V::*;
+        match *self {
+            M(major) => (major, 0, 0),
+            MM(major, minor) => (major, minor, 0),
+            MMP(major, minor, patch) => (major, minor, patch),
+        }
+    }
+}
+
+impl Ord for V {
+    fn cmp(&self, other: &V) -> cmp::Ordering {
+        self.mmp().cmp(&other.mmp())
+    }
+}
+
+impl PartialOrd for V {
+    fn partial_cmp(&self, other: &V) -> Option<cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialEq for V {
+    fn eq(&self, other: &V) -> bool {
+        self.mmp() == other.mmp()
+    }
+}
+
+impl fmt::Display for V {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::V::*;
+        match *self {
+            M(major) => write!(f, "{}", major),
+            MM(major, minor) => write!(f, "{}.{}", major, minor),
+            MMP(major, minor, patch) => write!(f, "{}.{}.{}", major, minor, patch),
+        }
+    }
+}
+
+struct VRange {
+    ge: Option<V>,
+    lt: Option<V>,
+}
+
+impl VRange {
+    fn new() -> Self {
+        VRange { ge: None, lt: None }
+    }
+
+    fn constrain_ge(&mut self, ge: V) -> &Self {
+        match self.ge {
+            Some(ref ge_) if &ge < ge_ => (),
+            _ => self.ge = Some(ge),
+        };
+        self
+    }
+
+    fn constrain_lt(&mut self, lt: V) -> &Self {
+        match self.lt {
+            Some(ref lt_) if &lt >= lt_ => (),
+            _ => self.lt = Some(lt),
+        };
+        self
+    }
+
+    fn to_deb_clause(&self, base: &str, suffix: &str) -> Result<Vec<String>> {
+        use debian::dependency::V::*;
+        match (&self.ge, &self.lt) {
+            (None, None) => Ok(vec![format!("{}{}", base, suffix)]),
+            (Some(ge), None) => Ok(vec![format!("{}{} (>= {}-~~)", base, suffix, ge)]),
+            (None, Some(lt)) => Ok(vec![format!("{}{} (<< {}-~~)", base, suffix, lt)]),
+            (Some(ge), Some(lt)) => {
+                if ge >= lt {
+                    debcargo_bail!("bad version range: >= {}, << {}", ge, lt);
+                }
+                let mut ranges = vec![];
+                let (lt_maj, lt_min, lt_pat) = lt.mmp();
+                let (ge_maj, ge_min, _ge_pat) = ge.mmp();
+
+                if ge_maj + 1 == lt_maj && lt_min == 0 && lt_pat == 0 {
+                    // upper bound doesn't restrict lower bound further if we include the major
+                    // part
+                    ranges.push((Some(M(ge_maj)), true, ge));
+                } else if ge_maj < lt_maj {
+                    // different major versions, unversioned package needs to satisfy
+                    ranges.push((None, true, ge));
+                    ranges.push((None, false, lt));
+                } else {
+                    assert_eq!(ge_maj, lt_maj);
+                    if ge_maj == 0 && ge_min + 1 == lt_min && lt_pat == 0 {
+                        // upper bound doesn't restrict lower bound further if we include 0.X
+                        ranges.push((Some(MM(ge_maj, ge_min)), true, ge));
+                    } else if ge_maj == 0 && ge_min < lt_min {
+                        // different 0.X versions, unversioned package needs to satisfy
+                        ranges.push((None, true, ge));
+                        ranges.push((None, false, lt));
+                    } else if ge_min < lt_min {
+                        // different minor versions within a major version, any package with the
+                        // corresponding major version can potentially satisfy
+                        ranges.push((Some(M(ge_maj)), true, ge));
+                        ranges.push((Some(M(lt_maj)), false, lt));
+                    } else {
+                        // just the patch level differs, but both ends restricted
+                        // any package with the corresponding major.minor version can potentially
+                        // satisfy
+                        assert_eq!(ge_min, lt_min);
+                        ranges.push((Some(MM(ge_maj, ge_min)), true, ge));
+                        ranges.push((Some(MM(lt_maj, lt_min)), false, lt));
+                    }
+                };
+                // unversioned package name is only provided by the non semver-suffixed packages
+                // if a range is only satisfiable by semver-suffixed variants in the archive, it
+                // needs to be collapsed/reduced accordingly
+                Ok(ranges
+                    .iter()
+                    .filter_map(|(ver, greater, cons)| match (ver, greater, cons) {
+                        (None, true, c) => Some(format!("{}{} (>= {}-~~)", base, suffix, c)),
+                        (None, false, c) => Some(format!("{}{} (<< {}-~~)", base, suffix, c)),
+                        (Some(ver), true, c) => {
+                            if c == &ver {
+                                // A-x >= x is redundant, drop the >=
+                                Some(format!("{}-{}{}", base, ver, suffix))
+                            } else {
+                                Some(format!("{}-{}{} (>= {}-~~)", base, ver, suffix, c))
+                            }
+                        }
+                        (Some(ver), false, c) => {
+                            if c == &ver {
+                                // A-x << x is unsatisfiable, drop it
+                                None
+                            } else {
+                                Some(format!("{}-{}{} (<< {}-~~)", base, ver, suffix, c))
+                            }
+                        }
+                    })
+                    .collect())
+            }
+        }
+    }
+}
+
+fn coerce_unacceptable_predicate<'a>(
+    dep: &Dependency,
+    p: &'a semver::Comparator,
+    allow_prerelease_deps: bool,
+) -> Result<&'a semver::Op> {
+    let mmp = &V::new(p)?;
+
+    // Cargo/semver and Debian handle pre-release versions quite
+    // differently, so a versioned Debian dependency cannot properly
+    // handle pre-release crates. This might be OK most of the time,
+    // coerce it to the non-pre-release version.
+    if !p.pre.is_empty() {
+        if allow_prerelease_deps || testing_ignore_debpolv() {
+            debcargo_warn!(
+                "Coercing removal of prerelease part of dependency: {} {:?}",
+                dep.package_name(),
+                p
+            )
+        } else {
+            debcargo_bail!(
+                "Cannot represent prerelease part of dependency: {} {:?}",
+                dep.package_name(),
+                p
+            )
+        }
+    }
+
+    use debian::dependency::V::M;
+    use semver::Op::*;
+    match (&p.op, mmp) {
+        (&Greater, &M(0)) => Ok(&p.op),
+        (&GreaterEq, &M(0)) => {
+            debcargo_warn!(
+                "Coercing unrepresentable dependency version predicate 'GtEq 0' to 'Gt 0': {} {:?}",
+                dep.package_name(),
+                p
+            );
+            Ok(&Greater)
+        }
+        // TODO: This will prevent us from handling wildcard dependencies with
+        // 0.0.0* so for now commenting this out.
+        // (_, &M(0)) => debcargo_bail!(
+        //     "Unrepresentable dependency version predicate: {} {:?}",
+        //     dep.package_name(),
+        //     p
+        // ),
+        (_, _) => Ok(&p.op),
+    }
+}
+
+fn generate_version_constraints(
+    vr: &mut VRange,
+    dep: &Dependency,
+    p: &semver::Comparator,
+    op: &semver::Op,
+) -> Result<()> {
+    let mmp = V::new(p)?;
+    use debian::dependency::V::*;
+    use semver::Op::*;
+    // see https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
+    // and https://docs.rs/semver/1/semver/enum.Op.html for semantics
+    match (*op, &mmp) {
+        (Less, &M(0)) | (Less, &MM(0, 0)) | (Less, &MMP(0, 0, 0)) => debcargo_bail!(
+            "Unrepresentable dependency version predicate: {} {:?}",
+            dep.package_name(),
+            p
+        ),
+        (Less, _) => {
+            vr.constrain_lt(mmp);
+        }
+        (LessEq, _) => {
+            vr.constrain_lt(mmp.inclast());
+        }
+        (Greater, _) => {
+            vr.constrain_ge(mmp.inclast());
+        }
+        (GreaterEq, _) => {
+            vr.constrain_ge(mmp);
+        }
+        (Exact, _) | (Wildcard, _) => {
+            vr.constrain_lt(mmp.inclast());
+            vr.constrain_ge(mmp);
+        }
+        (Tilde, &M(_)) | (Tilde, &MM(_, _)) => {
+            vr.constrain_lt(mmp.inclast());
+            vr.constrain_ge(mmp);
+        }
+        (Tilde, &MMP(major, minor, _)) => {
+            vr.constrain_lt(MM(major, minor + 1));
+            vr.constrain_ge(mmp);
+        }
+
+        (Caret, &MMP(0, 0, _)) => {
+            vr.constrain_lt(mmp.inclast());
+            vr.constrain_ge(mmp);
+        }
+        (Caret, &MMP(0, minor, _)) | (Caret, &MM(0, minor)) => {
+            vr.constrain_lt(MM(0, minor + 1));
+            vr.constrain_ge(mmp);
+        }
+        (Caret, &MMP(major, _, _)) | (Caret, &MM(major, _)) | (Caret, &M(major)) => {
+            vr.constrain_lt(M(major + 1));
+            vr.constrain_ge(mmp);
+        }
+
+        (_, _) => {
+            // https://github.com/dtolnay/semver/issues/262
+            panic!("Op is non-exhaustive for some reason");
+        }
+    }
+
+    Ok(())
+}
+
+/// Translates a Cargo dependency into a Debian package dependency.
+pub fn deb_dep(allow_prerelease_deps: bool, dep: &Dependency) -> Result<Vec<String>> {
+    let dep_dashed = base_deb_name(&dep.package_name());
+    let mut suffixes = Vec::new();
+    if dep.uses_default_features() {
+        suffixes.push("+default-dev".to_string());
+    }
+    for feature in dep.features() {
+        suffixes.push(format!("+{}-dev", base_deb_name(feature)));
+    }
+    if suffixes.is_empty() {
+        suffixes.push("-dev".to_string());
+    }
+    let req = semver::VersionReq::parse(&dep.version_req().to_string())?;
+    let mut deps = Vec::new();
+    for suffix in suffixes {
+        let base = format!("{}-{}", Package::pkg_prefix(), dep_dashed);
+        let mut vr = VRange::new();
+        for p in &req.comparators {
+            let op = coerce_unacceptable_predicate(dep, p, allow_prerelease_deps)?;
+            generate_version_constraints(&mut vr, dep, p, op)?;
+        }
+        deps.extend(vr.to_deb_clause(&base, &suffix)?);
+    }
+    Ok(deps)
+}
+
+pub fn deb_deps(allow_prerelease_deps: bool, cdeps: &[Dependency]) -> Result<Vec<String>> // result is an AND-clause
+{
+    let mut deps = Vec::new();
+    for dep in cdeps {
+        deps.extend(
+            deb_dep(allow_prerelease_deps, dep)?
+                .iter()
+                .map(String::to_string),
+        );
+    }
+    deps.sort();
+    deps.dedup();
+    Ok(deps)
+}
+
+pub fn deb_dep_add_nocheck(x: &str) -> String {
+    x.split('|')
+        .map(|x| x.trim_end().to_string() + " <!nocheck> ")
+        .join("|")
+        .trim_end()
+        .to_string()
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/debian/dependency/tests.rs b/src/debian/dependency/tests.rs
new file mode 100644 (file)
index 0000000..65f28c1
--- /dev/null
@@ -0,0 +1,283 @@
+use crate::debian::deb_dep_add_nocheck;
+use crate::debian::dependency::{VRange, V};
+
+#[test]
+fn test_v_new_mmp() {
+    let v = V::new(&semver::Comparator::parse("0.9.7").unwrap()).unwrap();
+
+    assert_eq!((0, 9, 7), v.mmp());
+}
+
+#[test]
+fn test_v_new_inclast() {
+    let v = V::new(&semver::Comparator::parse("0.9.7").unwrap()).unwrap();
+
+    assert_eq!((0, 9, 8), v.inclast().mmp());
+}
+
+#[test]
+fn test_v_neq() {
+    let v1 = V::new(&semver::Comparator::parse("0.9.7").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.9.8").unwrap()).unwrap();
+
+    assert!(v1 != v2);
+}
+
+#[test]
+fn test_v_eq() {
+    let v1 = V::new(&semver::Comparator::parse("0.10.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    assert!(v1 == v2);
+}
+
+#[test]
+fn test_v_display() {
+    let v1 = V::new(&semver::Comparator::parse("0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+    let v3 = V::new(&semver::Comparator::parse("0.10.0").unwrap()).unwrap();
+
+    assert_eq!("0", v1.to_string());
+    assert_eq!("0.10", v2.to_string());
+    assert_eq!("0.10.0", v3.to_string());
+}
+
+#[test]
+fn test_v_range() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    assert!(vr.ge.is_none());
+    assert!(vr.lt.is_none());
+
+    vr.constrain_ge(v1.clone());
+    assert!(vr.ge.is_some());
+    assert!(vr.ge.as_ref().unwrap() == &v1);
+    assert!(vr.ge.as_ref().unwrap() < &v2);
+    assert!(vr.lt.is_none());
+
+    vr.constrain_lt(v2.clone());
+    assert!(vr.ge.is_some());
+    assert!(vr.lt.is_some());
+    assert!(vr.ge.as_ref().unwrap() == &v1);
+    assert!(vr.lt.as_ref().unwrap() == &v2);
+}
+
+#[test]
+fn test_v_range_to_deb_clause_empty() {
+    let vr = VRange::new();
+
+    assert_eq!(
+        vec!["base+feature"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_ge_only() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.9-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_lt_only() {
+    let v1 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_lt(v1);
+
+    assert_eq!(
+        vec!["base+feature (<< 0.10-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_one_apart() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.10").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base-0.9+feature"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_two_apart() {
+    let v1 = V::new(&semver::Comparator::parse("0.9").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.11").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.9-~~)", "base+feature (<< 0.11-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 0.1.2").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.4").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.1.2-~~)", "base+feature (<< 0.4-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_complicated() {
+    let v1 = V::new(&semver::Comparator::parse(">= 0.1.2").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.1.5").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec![
+            "base-0.1+feature (>= 0.1.2-~~)",
+            "base-0.1+feature (<< 0.1.5-~~)"
+        ],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_minor_more_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 0.1.2").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("0.4.5").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 0.1.2-~~)", "base+feature (<< 0.4.5-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_one_apart() {
+    let v1 = V::new(&semver::Comparator::parse("9.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("10.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base-9+feature"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_two_apart() {
+    let v1 = V::new(&semver::Comparator::parse("9.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("11.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 9.0-~~)", "base+feature (<< 11.0-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 1.2.3").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("4.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 1.2.3-~~)", "base+feature (<< 4.0-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_complicated() {
+    let v1 = V::new(&semver::Comparator::parse(">= 1.2.3").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("1.9.9").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec![
+            "base-1+feature (>= 1.2.3-~~)",
+            "base-1+feature (<< 1.9.9-~~)"
+        ],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_major_more_complicated_apart() {
+    let v1 = V::new(&semver::Comparator::parse(">= 1.2.3").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("4.5.6").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v1);
+    vr.constrain_lt(v2);
+
+    assert_eq!(
+        vec!["base+feature (>= 1.2.3-~~)", "base+feature (<< 4.5.6-~~)"],
+        vr.to_deb_clause("base", "+feature").unwrap()
+    )
+}
+
+#[test]
+fn test_v_range_to_deb_clause_bad_range() {
+    let v1 = V::new(&semver::Comparator::parse("9.0").unwrap()).unwrap();
+    let v2 = V::new(&semver::Comparator::parse("11.0").unwrap()).unwrap();
+
+    let mut vr = VRange::new();
+    vr.constrain_ge(v2);
+    vr.constrain_lt(v1);
+
+    let err = vr.to_deb_clause("base", "+feature");
+    assert!(err.is_err());
+    assert_eq!(
+        "bad version range: >= 11.0, << 9.0",
+        err.unwrap_err().to_string()
+    );
+}
+
+#[test]
+fn test_deb_dep_add_nocheck() {
+    let result = deb_dep_add_nocheck(" librust-sequoia-policy-config-0.7+default-dev | librust-sequoia-policy-config-0.6+default-dev");
+
+    let expected = " librust-sequoia-policy-config-0.7+default-dev <!nocheck> | librust-sequoia-policy-config-0.6+default-dev <!nocheck>";
+
+    assert_eq!(expected, result);
+}
diff --git a/src/debian/licenses/AGPL-3.0 b/src/debian/licenses/AGPL-3.0
new file mode 100644 (file)
index 0000000..dba13ed
--- /dev/null
@@ -0,0 +1,661 @@
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/src/debian/licenses/Apache-2.0 b/src/debian/licenses/Apache-2.0
new file mode 100644 (file)
index 0000000..d69cdd1
--- /dev/null
@@ -0,0 +1,2 @@
+Debian systems provide the Apache 2.0 license in
+/usr/share/common-licenses/Apache-2.0
diff --git a/src/debian/licenses/BSD-2-Clause b/src/debian/licenses/BSD-2-Clause
new file mode 100644 (file)
index 0000000..d17fad3
--- /dev/null
@@ -0,0 +1,20 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/debian/licenses/BSD-3-Clause b/src/debian/licenses/BSD-3-Clause
new file mode 100644 (file)
index 0000000..689c723
--- /dev/null
@@ -0,0 +1,24 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/debian/licenses/CC0-1.0 b/src/debian/licenses/CC0-1.0
new file mode 100644 (file)
index 0000000..e37e562
--- /dev/null
@@ -0,0 +1,2 @@
+Debian systems provide the CC0 1.0 Universal License in
+/usr/share/common-licenses/CC0-1.0
diff --git a/src/debian/licenses/GPL-2.0 b/src/debian/licenses/GPL-2.0
new file mode 100644 (file)
index 0000000..0c94208
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the GPL 2.0 in /usr/share/common-licenses/GPL-2
diff --git a/src/debian/licenses/GPL-3.0 b/src/debian/licenses/GPL-3.0
new file mode 100644 (file)
index 0000000..4e80768
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the GPL 3.0 in /usr/share/common-licenses/GPL-3
diff --git a/src/debian/licenses/ISC b/src/debian/licenses/ISC
new file mode 100644 (file)
index 0000000..8351a30
--- /dev/null
@@ -0,0 +1,11 @@
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/debian/licenses/LGPL-2.0 b/src/debian/licenses/LGPL-2.0
new file mode 100644 (file)
index 0000000..5fa5065
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the LGPL 2.0 in /usr/share/common-licenses/LGPL-2
diff --git a/src/debian/licenses/LGPL-2.1 b/src/debian/licenses/LGPL-2.1
new file mode 100644 (file)
index 0000000..32f41bb
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the LGPL 2.1 in /usr/share/common-licenses/LGPL-2.1
diff --git a/src/debian/licenses/LGPL-3.0 b/src/debian/licenses/LGPL-3.0
new file mode 100644 (file)
index 0000000..91e41a7
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the LGPL 3.0 in /usr/share/common-licenses/LGPL-3
diff --git a/src/debian/licenses/MIT b/src/debian/licenses/MIT
new file mode 100644 (file)
index 0000000..50b3cf0
--- /dev/null
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/debian/licenses/MITNFA b/src/debian/licenses/MITNFA
new file mode 100644 (file)
index 0000000..8eff3c8
--- /dev/null
@@ -0,0 +1,29 @@
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+Distributions of all or part of the Software intended to be used
+by the recipients as they would use the unmodified Software,
+containing modifications that substantially alter, remove, or
+disable functionality of the Software, outside of the documented
+configuration mechanisms provided by the Software, shall be
+modified such that the Original Author's bug reporting email
+addresses and urls are either replaced with the contact information
+of the parties responsible for the changes, or removed entirely.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/debian/licenses/MPL-1.1 b/src/debian/licenses/MPL-1.1
new file mode 100644 (file)
index 0000000..f07159d
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the MPL 1.1 in /usr/share/common-licenses/MPL-1.1
diff --git a/src/debian/licenses/MPL-2.0 b/src/debian/licenses/MPL-2.0
new file mode 100644 (file)
index 0000000..8dcf8f1
--- /dev/null
@@ -0,0 +1 @@
+Debian systems provide the MPL 2.0 in /usr/share/common-licenses/MPL-2.0
diff --git a/src/debian/licenses/Unlicense b/src/debian/licenses/Unlicense
new file mode 100644 (file)
index 0000000..b3dbff0
--- /dev/null
@@ -0,0 +1,22 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/debian/licenses/Zlib b/src/debian/licenses/Zlib
new file mode 100644 (file)
index 0000000..480c61e
--- /dev/null
@@ -0,0 +1,15 @@
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
diff --git a/src/debian/mod.rs b/src/debian/mod.rs
new file mode 100644 (file)
index 0000000..4dc1e20
--- /dev/null
@@ -0,0 +1,1282 @@
+use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
+use std::fs;
+use std::io::{self, ErrorKind, Read, Seek, Write as IoWrite};
+use std::ops::Deref;
+#[cfg(unix)]
+use std::os::unix::fs::PermissionsExt;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use std::str::FromStr;
+
+use anyhow::format_err;
+use chrono::{self, Datelike};
+use control::BuildDeps;
+use flate2::read::GzDecoder;
+use flate2::write::GzEncoder;
+use flate2::Compression;
+use itertools::Itertools;
+use regex::Regex;
+use tar::{Archive, Builder};
+use tempfile;
+
+use crate::config::{package_field_for_feature, testing_ignore_debpolv, Config, PackageKey};
+use crate::crates::{
+    all_dependencies_and_features, show_dep, transitive_deps, CrateDepInfo, CrateInfo,
+};
+use crate::errors::*;
+use crate::util::{self, copy_tree, expect_success, get_transitive_val, traverse_depth};
+
+use self::changelog::{ChangelogEntry, ChangelogIterator};
+use self::control::{base_deb_name, deb_upstream_version};
+use self::control::{Description, Package, PkgTest, Source};
+use self::copyright::debian_copyright;
+pub use self::dependency::{deb_dep_add_nocheck, deb_deps};
+
+pub mod changelog;
+pub mod control;
+pub mod copyright;
+mod dependency;
+
+pub struct DebInfo {
+    upstream_name: String,
+    /// Debian package name without `rust-` prefix or any semver suffix
+    base_package_name: String,
+    /// Package name suffix after the base package name.
+    /// Some implies semver_suffix, i.e. Some("") is different from None
+    name_suffix: Option<String>,
+    uscan_version_pattern: Option<String>,
+    /// Debian package name without `rust-` prefix
+    package_name: String,
+    deb_upstream_version: String,
+    debcargo_version: String,
+    package_source_dir: PathBuf,
+    orig_tarball_path: PathBuf,
+}
+
+impl DebInfo {
+    pub fn new(crate_info: &CrateInfo, debcargo_version: &str, semver_suffix: bool) -> Self {
+        let upstream_name = crate_info.package_id().name().to_string();
+        let name_dashed = base_deb_name(&upstream_name);
+        let base_package_name = name_dashed.to_lowercase();
+        let (name_suffix, uscan_version_pattern, package_name) = if semver_suffix {
+            let semver = crate_info.semver();
+            let name_suffix = format!("-{}", &semver);
+            // See `man uscan` description of @ANY_VERSION@ on how these
+            // regex patterns were built.
+            let uscan = format!("[-_]?({}\\.\\d[\\-+\\.:\\~\\da-zA-Z]*)", &semver);
+            let pkgname = format!("{}{}", base_package_name, &name_suffix);
+            (Some(name_suffix), Some(uscan), pkgname)
+        } else {
+            (None, None, base_package_name.clone())
+        };
+        let deb_upstream_version = deb_upstream_version(crate_info.version());
+        let package_source_dir = PathBuf::from(format!(
+            "{}-{}-{}",
+            Source::pkg_prefix(),
+            package_name,
+            deb_upstream_version
+        ));
+        let orig_tarball_path = PathBuf::from(format!(
+            "{}-{}_{}.orig.tar.gz",
+            Source::pkg_prefix(),
+            package_name,
+            deb_upstream_version
+        ));
+
+        DebInfo {
+            upstream_name,
+            base_package_name,
+            name_suffix,
+            uscan_version_pattern,
+            package_name,
+            deb_upstream_version,
+            debcargo_version: debcargo_version.to_string(),
+            package_source_dir,
+            orig_tarball_path,
+        }
+    }
+
+    pub fn upstream_name(&self) -> &str {
+        self.upstream_name.as_str()
+    }
+
+    pub fn base_package_name(&self) -> &str {
+        self.base_package_name.as_str()
+    }
+
+    pub fn name_suffix(&self) -> Option<&str> {
+        self.name_suffix.as_deref()
+    }
+
+    pub fn package_name(&self) -> &str {
+        self.package_name.as_str()
+    }
+
+    pub fn deb_upstream_version(&self) -> &str {
+        self.deb_upstream_version.as_str()
+    }
+
+    pub fn debcargo_version(&self) -> &str {
+        self.debcargo_version.as_str()
+    }
+
+    pub fn package_source_dir(&self) -> &Path {
+        self.package_source_dir.as_ref()
+    }
+
+    pub fn orig_tarball_path(&self) -> &Path {
+        self.orig_tarball_path.as_ref()
+    }
+}
+
+pub fn prepare_orig_tarball(
+    crate_info: &CrateInfo,
+    tarball: &Path,
+    src_modified: bool,
+    output_dir: &Path,
+) -> Result<()> {
+    let crate_file = crate_info.crate_file();
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(".")?;
+    let temp_archive_path = tempdir.path().join(tarball);
+
+    let mut create = fs::OpenOptions::new();
+    create.write(true).create_new(true);
+
+    if src_modified {
+        debcargo_info!("crate tarball was modified; repacking for debian");
+        let mut f = crate_file.file();
+        f.seek(io::SeekFrom::Start(0))?;
+        let mut archive = Archive::new(GzDecoder::new(f));
+        let mut new_archive = Builder::new(GzEncoder::new(
+            create.open(&temp_archive_path)?,
+            Compression::best(),
+        ));
+
+        for entry in archive.entries()? {
+            let entry = entry?;
+            let path = entry.path()?.into_owned();
+            if path.ends_with("Cargo.toml") && path.iter().count() == 2 {
+                // Put the rewritten and original Cargo.toml back into the orig tarball
+                let mut new_archive_append = |name: &str| {
+                    let mut header = entry.header().clone();
+                    let srcpath = output_dir.join(name);
+                    header.set_path(path.parent().unwrap().join(name))?;
+                    header.set_size(fs::metadata(&srcpath)?.len());
+                    header.set_cksum();
+                    new_archive.append(&header, fs::File::open(&srcpath)?)
+                };
+                new_archive_append("Cargo.toml")?;
+                new_archive_append("Cargo.toml.orig")?;
+            } else {
+                match crate_info.filter_path(&entry.path()?) {
+                    Err(e) => debcargo_bail!(e),
+                    Ok(r) => {
+                        if !r {
+                            new_archive.append_data(&mut entry.header().clone(), path, entry)?;
+                        } else {
+                            writeln!(
+                                io::stderr(),
+                                "Filtered out files from .orig.tar.gz: {:?}",
+                                &entry.path()?
+                            )?;
+                        }
+                    }
+                }
+            }
+        }
+
+        new_archive.finish()?;
+    } else {
+        fs::copy(crate_file.path(), &temp_archive_path)?;
+    }
+
+    fs::rename(temp_archive_path, tarball)?;
+    Ok(())
+}
+
+pub fn apply_overlay_and_patches(
+    crate_info: &mut CrateInfo,
+    config_path: Option<&Path>,
+    config: &Config,
+    output_dir: &Path,
+) -> Result<tempfile::TempDir> {
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(".")?;
+    let overlay = config.overlay_dir(config_path);
+    if let Some(p) = overlay.as_ref() {
+        for anc in tempdir.path().ancestors() {
+            if p.as_path() == anc {
+                debcargo_bail!(
+                    "Aborting: refusing to copy an ancestor {} into a descendant {}",
+                    p.as_path().display(),
+                    tempdir.path().display(),
+                );
+            }
+        }
+        copy_tree(p.as_path(), tempdir.path())?;
+    }
+    if tempdir.path().join("control").exists() {
+        debcargo_warn!(
+            "Most of the time you shouldn't overlay debian/control, \
+it's a maintenance burden. Use debcargo.toml instead."
+        )
+    }
+    // apply patches to Cargo.toml in case they exist, and re-read it
+    if tempdir.path().join("patches").join("series").exists() {
+        debcargo_info!("applying patches..");
+        let output_dir = &fs::canonicalize(output_dir)?;
+        let stderr = || {
+            // create a new owned handle to stderr
+            fs::OpenOptions::new()
+                .append(true)
+                .open("/dev/stderr")
+                .unwrap()
+        };
+        // common case, patches might need rebasing!
+        if let Err(err) = expect_success(
+            Command::new("quilt")
+                .stdout(stderr())
+                .current_dir(output_dir)
+                .env("QUILT_PATCHES", tempdir.path().join("patches"))
+                .args(["push", "--quiltrc=-", "-a"]),
+            "failed to apply patches using quilt",
+        ) {
+            debcargo_warn!(format!("{err}, attempting cleanup"));
+            let _ = expect_success(
+                Command::new("quilt")
+                    .stdout(stderr())
+                    .current_dir(output_dir)
+                    .env("QUILT_PATCHES", tempdir.path().join("patches"))
+                    .args(["pop", "--quiltrc=-", "-a", "-f"]),
+                "failed to unapply partially applied patches",
+            );
+            fs::remove_dir_all(output_dir.join(".pc"))?;
+            debcargo_bail!("applying patches failed! see above for details..");
+        }
+        debcargo_info!("reloading Cargo.toml..");
+        crate_info.replace_manifest(&output_dir.join("Cargo.toml"))?;
+
+        // this should never fail!
+        debcargo_info!("unapplying patches again..");
+        expect_success(
+            Command::new("quilt")
+                .stdout(stderr())
+                .current_dir(output_dir)
+                .env("QUILT_PATCHES", tempdir.path().join("patches"))
+                .args(["pop", "--quiltrc=-", "-a"]),
+            "failed to unapply patches",
+        )?;
+        fs::remove_dir_all(output_dir.join(".pc"))?;
+    }
+    Ok(tempdir)
+}
+
+#[allow(clippy::too_many_arguments)]
+pub fn prepare_debian_folder(
+    crate_info: &mut CrateInfo,
+    deb_info: &DebInfo,
+    config_path: Option<&Path>,
+    config: &Config,
+    output_dir: &Path,
+    tempdir: &tempfile::TempDir,
+    changelog_ready: bool,
+    copyright_guess_harder: bool,
+    overlay_write_back: bool,
+) -> Result<()> {
+    let mut create = fs::OpenOptions::new();
+    create.write(true).create_new(true);
+
+    let crate_name = crate_info.package_id().name();
+    let crate_version = crate_info.package_id().version();
+    let upstream_name = deb_info.upstream_name();
+
+    let maintainer = config.maintainer();
+    let uploaders: Vec<&str> = config
+        .uploaders()
+        .into_iter()
+        .flatten()
+        .map(String::as_str)
+        .collect();
+
+    let mut new_hints = vec![];
+    let mut file = |name: &str| {
+        let path = tempdir.path();
+        let f = path.join(name);
+        fs::create_dir_all(f.parent().unwrap())?;
+        create.open(&f).or_else(|e| match e.kind() {
+            ErrorKind::AlreadyExists => {
+                let hintname = name.to_owned() + util::HINT_SUFFIX;
+                let hint = path.join(&hintname);
+                if hint.exists() {
+                    fs::remove_file(&hint)?;
+                }
+                new_hints.push(hintname);
+                create.open(&hint)
+            }
+            _ => Err(e),
+        })
+    };
+
+    // debian/cargo-checksum.json
+    {
+        let checksum = crate_info
+            .checksum()
+            .unwrap_or("Could not get crate checksum");
+        let mut cargo_checksum_json = file("cargo-checksum.json")?;
+        writeln!(
+            cargo_checksum_json,
+            r#"{{"package":"{}","files":{{}}}}"#,
+            checksum
+        )?;
+    }
+
+    // debian/copyright
+    {
+        let mut copyright = io::BufWriter::new(file("copyright")?);
+        let year_range = if changelog_ready {
+            // if changelog is ready, unconditionally read the year range from it
+            changelog_first_last(tempdir.path())?
+        } else {
+            // otherwise use the first date if it exists
+            let last = chrono::Local::now().year();
+            match changelog_first_last(tempdir.path()) {
+                Ok((first, _)) => (first, last),
+                Err(_) => (last, last),
+            }
+        };
+        let dep5_copyright = debian_copyright(
+            output_dir,
+            crate_info.manifest(),
+            crate_info.manifest_path(),
+            maintainer,
+            &uploaders,
+            year_range,
+            copyright_guess_harder,
+        )?;
+        write!(copyright, "{}", dep5_copyright)?;
+    }
+
+    // debian/watch
+    {
+        let mut watch = file("watch")?;
+        match config.crate_src_path(config_path) {
+            Some(_) => write!(watch, "FIXME add uscan directive for local crate")?,
+            None => {
+                let uscan_version_pattern = deb_info
+                    .uscan_version_pattern
+                    .as_ref()
+                    .map_or_else(|| "@ANY_VERSION@".to_string(), |ref s| s.to_string());
+                writeln!(watch, "Version: 5\n")?;
+                writeln!(
+                    watch,
+                    "Source: https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/{name}",
+                    name = upstream_name,
+                )?;
+                writeln!(
+                    watch,
+                    "Matching-Pattern:  .*/crates/{name}/{version_pattern}/download",
+                    name = upstream_name,
+                    version_pattern = uscan_version_pattern
+                )?;
+                writeln!(
+                    watch,
+                    r"Filenamemangle: s/.*\/(.*)\/download/{name}-$1\.tar\.gz/g",
+                    name = upstream_name,
+                )?;
+                writeln!(
+                    watch,
+                    r"Uversionmangle: s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\.?\d*)$/$1~$2/"
+                )?;
+            }
+        };
+    }
+
+    // debian/source/format
+    {
+        fs::create_dir_all(tempdir.path().join("source"))?;
+        let mut source_format = file("source/format")?;
+        writeln!(source_format, "3.0 (quilt)")?;
+    }
+
+    // debian/control & debian/tests/control
+    let (source, has_dev_depends, default_test_broken) =
+        prepare_debian_control(deb_info, crate_info, config, &mut file)?;
+
+    // for testing only, debian/debcargo_testing_bin/env
+    if testing_ignore_debpolv() {
+        fs::create_dir_all(tempdir.path().join("debcargo_testing_bin"))?;
+        let mut env_hack = file("debcargo_testing_bin/env")?;
+        #[cfg(unix)]
+        env_hack.set_permissions(fs::Permissions::from_mode(0o777))?;
+        // intercept calls to dh-cargo-built-using
+        writeln!(
+            env_hack,
+            r#"#!/bin/sh
+case "$*" in */usr/share/cargo/bin/dh-cargo-built-using*)
+echo "debcargo testing: suppressing dh-cargo-built-using";;
+*) /usr/bin/env "$@";; esac
+"#
+        )?;
+    }
+
+    // debian/rules
+    {
+        let mut rules = file("rules")?;
+        #[cfg(unix)]
+        rules.set_permissions(fs::Permissions::from_mode(0o777))?;
+        if has_dev_depends || testing_ignore_debpolv() {
+            // don't run any tests, we don't want extra B-D on dev-depends
+            // this could potentially cause B-D cycles so we avoid it
+            //
+            // also don't run crate tests during integration testing since some
+            // of them are brittle and fail; the purpose is to test debcargo
+            // not the actual crates
+            write!(
+                rules,
+                "{}",
+                concat!(
+                    "#!/usr/bin/make -f\n",
+                    "%:\n",
+                    "\tdh $@ --buildsystem cargo\n"
+                )
+            )?;
+            // some crates need nightly to compile, annoyingly. only do this in
+            // testing; outside of testing the user should explicitly override
+            // debian/rules to do this
+            if testing_ignore_debpolv() {
+                writeln!(rules, "export RUSTC_BOOTSTRAP := 1")?;
+                writeln!(
+                    rules,
+                    "export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)"
+                )?;
+            }
+        } else {
+            write!(
+                rules,
+                "{}{}",
+                concat!(
+                    "#!/usr/bin/make -f\n",
+                    "%:\n",
+                    "\tdh $@ --buildsystem cargo\n",
+                    "\n",
+                    "override_dh_auto_test:\n",
+                ),
+                // TODO: this logic is slightly brittle if another feature
+                // "provides" the default feature. In this case, you need to
+                // set test_is_broken explicitly on package."lib+default" and
+                // not package."lib+theotherfeature".
+                if default_test_broken {
+                    "\tdh_auto_test -- test --all || true\n"
+                } else {
+                    "\tdh_auto_test -- test --all\n"
+                },
+            )?;
+        }
+    }
+
+    // debian/changelog
+    if !changelog_ready {
+        let author = control::get_deb_author()?;
+        let crate_src = match config.crate_src_path(config_path) {
+            Some(_) => "local source",
+            None => "crates.io",
+        };
+        let autogenerated_item = format!(
+            "  * Package {} {} from {} using debcargo {}",
+            &crate_name,
+            &crate_version,
+            &crate_src,
+            deb_info.debcargo_version()
+        );
+        let autogenerated_re = Regex::new(&format!(
+            r"^  \* Package (.*) (.*) from {} using debcargo (.*)$",
+            &crate_src
+        ))?;
+
+        // Special-case d/changelog:
+        let (mut changelog, changelog_data) = changelog_or_new(tempdir.path())?;
+        let (changelog_old, mut changelog_items, deb_version_suffix) = {
+            let ver_bump = &|e: &Option<&str>| -> Result<Option<String>> {
+                Ok(match e {
+                    Some(x) => {
+                        let e = ChangelogEntry::from_str(x)?;
+                        if e.version_parts().0 == deb_info.deb_upstream_version() {
+                            Some(e.deb_version_suffix_bump())
+                        } else {
+                            None
+                        }
+                    }
+                    None => None,
+                })
+            };
+            let mut chit = ChangelogIterator::from(&changelog_data);
+            let e1 = chit.next();
+            match e1 {
+                // If the first entry has changelog::DEFAULT_DIST then write over it smartly
+                Some(x) if x.contains(changelog::DEFAULT_DIST) => {
+                    let mut e = ChangelogEntry::from_str(x)?;
+                    if author == e.maintainer {
+                        if let Some(pos) = e.items.iter().position(|x| autogenerated_re.is_match(x))
+                        {
+                            e.items[pos] = autogenerated_item;
+                        } else {
+                            e.items.push(autogenerated_item);
+                        }
+                    } else {
+                        // If unreleased changelog is by someone else, preserve their entries
+                        e.items.insert(0, autogenerated_item);
+                        e.items.insert(1, "".to_string());
+                        let ename = e.maintainer_name();
+                        e.items.insert(2, format!("  [ {} ]", ename));
+                    }
+                    (&changelog_data[x.len()..], e.items, ver_bump(&chit.next())?)
+                }
+                // Otherwise prepend a new entry to the existing entries
+                _ => (
+                    changelog_data.as_str(),
+                    vec![autogenerated_item],
+                    ver_bump(&e1)?,
+                ),
+            }
+        };
+
+        let source_deb_version = format!(
+            "{}-{}",
+            deb_info.deb_upstream_version(),
+            &deb_version_suffix.unwrap_or_else(|| "1".to_string())
+        );
+        if !uploaders.contains(&author.as_str()) {
+            debcargo_warn!(
+                "You ({}) are not in Uploaders; adding \"Team upload\" to d/changelog",
+                author
+            );
+            if !changelog_items.contains(&changelog::COMMENT_TEAM_UPLOAD.to_string()) {
+                changelog_items.insert(0, changelog::COMMENT_TEAM_UPLOAD.to_string());
+            }
+        }
+        let changelog_new_entry = ChangelogEntry::new(
+            source.name().to_string(),
+            source_deb_version,
+            changelog::DEFAULT_DIST.to_string(),
+            "urgency=medium".to_string(),
+            author,
+            changelog::local_now(),
+            changelog_items,
+        );
+
+        changelog.seek(io::SeekFrom::Start(0))?;
+        if changelog_old.is_empty() {
+            write!(changelog, "{}", changelog_new_entry)?;
+        } else {
+            write!(changelog, "{}\n{}", changelog_new_entry, changelog_old)?;
+        }
+        // the new file might be shorter, truncate it to the current cursor position
+        let pos = changelog.stream_position()?;
+        changelog.set_len(pos)?;
+    }
+
+    if overlay_write_back {
+        let overlay = config.overlay_dir(config_path);
+        if let Some(p) = overlay.as_ref() {
+            if !changelog_ready {
+                // Special-case d/changelog:
+                // Always write it back, this is safe because of our prepending logic
+                new_hints.push("changelog".to_string());
+            }
+            for hint in &new_hints {
+                let newpath = tempdir.path().join(hint);
+                let oldpath = p.join(hint);
+                fs::copy(newpath, oldpath).expect("could not write back");
+                debcargo_info!("Wrote back file to overlay: {}", hint);
+            }
+        }
+    }
+
+    fs::rename(tempdir.path(), output_dir.join("debian"))?;
+    Ok(())
+}
+
+fn prepare_debian_control<F: FnMut(&str) -> std::result::Result<fs::File, io::Error>>(
+    deb_info: &DebInfo,
+    crate_info: &CrateInfo,
+    config: &Config,
+    mut file: F,
+) -> Result<(Source, bool, bool)> {
+    let crate_name = crate_info.crate_name();
+    let deb_upstream_version = deb_info.deb_upstream_version();
+    let base_pkgname = deb_info.base_package_name();
+    let name_suffix = deb_info.name_suffix();
+
+    let lib = crate_info.is_lib();
+    let mut bins = crate_info.get_binary_targets();
+    if lib && !bins.is_empty() && !config.build_bin_package() {
+        bins.clear();
+    }
+    let bin_name = if config.bin_name.eq(&Config::default().bin_name) {
+        let default_bin_name = deb_info.base_package_name();
+        if !bins.is_empty() {
+            debcargo_info!(
+                "Generate binary crate with default name '{}', set bin_name to override or bin = false to disable.",
+                &default_bin_name
+            );
+        }
+        default_bin_name
+    } else {
+        config.bin_name.as_str()
+    };
+
+    let maintainer = config.maintainer();
+    let requires_root = config.requires_root();
+    let uploaders: Vec<&str> = config
+        .uploaders()
+        .into_iter()
+        .flatten()
+        .map(String::as_str)
+        .collect();
+
+    let features_with_deps = all_dependencies_and_features(crate_info.manifest());
+    let dev_depends = deb_deps(config.allow_prerelease_deps, &crate_info.dev_dependencies())?;
+    let has_dev_deps = !dev_depends.is_empty();
+    log::trace!(
+        "features_with_deps: {:?}",
+        features_with_deps
+            .iter()
+            .map(|(&f, (ff, dd))| { (f, (ff, dd.iter().map(show_dep).collect::<Vec<_>>())) })
+            .collect::<Vec<_>>()
+    );
+    let meta = crate_info.metadata();
+
+    // debian/tests/control, preparation
+    let test_is_marked_broken = |f: &str| config.package_test_is_broken(PackageKey::feature(f));
+    let test_is_broken = |f: &str| {
+        let getparents = |f: &str| features_with_deps.get(f).map(|(d, _)| d);
+        match get_transitive_val(&getparents, &test_is_marked_broken, f) {
+            Err((k, vv)) => debcargo_bail!(
+                "{} {}: {}: {:?}",
+                "error trying to recursively determine test_is_broken for",
+                k,
+                "dependencies have inconsistent config values",
+                vv
+            ),
+            Ok(v) => Ok(v.unwrap_or(false)),
+        }
+    };
+
+    let test_architecture = |f: &str| {
+        let getparents = |f: &str| features_with_deps.get(f).map(|(d, _)| d);
+        let feature_get_test_architecture =
+            |f: &str| config.package_test_architecture(PackageKey::feature(f));
+        match get_transitive_val(&getparents, &feature_get_test_architecture, f) {
+            Err((k, vv)) => debcargo_bail!(
+                "{} {}: {}: {:?}",
+                "error trying to recursively determine test_architecture for",
+                k,
+                "dependencies have inconsistent config values",
+                vv
+            ),
+            Ok(Some(v)) if v.is_empty() => Ok(None), // allow resetting via explicit empty list
+            Ok(other) => Ok(other),
+        }
+    };
+
+    let build_deps = {
+        let mut build_deps = BuildDeps::default();
+        // these are needed for the clean target
+        build_deps.build_depends.extend(
+            ["debhelper-compat (= 13)", "dh-sequence-cargo"]
+                .iter()
+                .map(|x| x.to_string()),
+        );
+
+        // note: please keep this in sync with build_order::dep_features
+        let (default_features, default_deps) = transitive_deps(&features_with_deps, "default")?;
+        //debcargo_info!("default_features: {:?}", default_features);
+        //debcargo_info!("default_deps: {:?}", deb_deps(config, &default_deps)?);
+        let extra_override_deps = package_field_for_feature(
+            &|x| config.package_depends(x),
+            PackageKey::feature("default"),
+            &default_features,
+        );
+        let build_deps_arch = toolchain_deps(&crate_info.rust_version())
+            .into_iter()
+            .chain(deb_deps(config.allow_prerelease_deps, &default_deps)?)
+            .chain(extra_override_deps);
+        if !bins.is_empty() {
+            build_deps.build_depends_arch.extend(build_deps_arch);
+        } else {
+            assert!(lib);
+            build_deps
+                .build_depends_arch
+                .extend(build_deps_arch.map(|d| {
+                    if config.skip_nocheck().unwrap_or(false) {
+                        d
+                    } else {
+                        deb_dep_add_nocheck(&d)
+                    }
+                }));
+        }
+        build_deps
+    };
+    let test_deps: Vec<String> = Some(rustc_dep(&crate_info.rust_version(), false))
+        .into_iter()
+        .chain(dev_depends)
+        .collect();
+
+    // prefer Cargo.toml homepage, fallback to Cargo.toml repository
+    let homepage = meta
+        .homepage
+        .as_deref()
+        .or(meta.repository.as_deref())
+        .unwrap_or("");
+
+    let mut source = Source::new(
+        base_pkgname,
+        name_suffix,
+        crate_name,
+        homepage,
+        lib,
+        maintainer.to_string(),
+        uploaders.iter().map(|s| s.to_string()).collect(),
+        build_deps,
+        requires_root.cloned(),
+    )?;
+
+    // If source overrides are present update related parts.
+    source.apply_overrides(config);
+
+    let mut control = io::BufWriter::new(file("control")?);
+    write!(control, "{}", source)?;
+
+    // Summary and description generated from Cargo.toml
+    let (crate_summary, crate_description) = crate_info.get_summary_description();
+    let summary_prefix = crate_summary.unwrap_or(format!("Rust crate \"{}\"", crate_name));
+    let description_prefix = {
+        let tmp = crate_description.unwrap_or_default();
+        if tmp.is_empty() {
+            tmp
+        } else {
+            format!("{}\n.\n", tmp)
+        }
+    };
+
+    if lib {
+        // debian/tests/control
+        let all_features: Vec<&str> = features_with_deps.keys().copied().collect();
+        let all_features_test_broken = match test_is_marked_broken("@") {
+            Some(v) => v,
+            None => all_features
+                .iter()
+                .any(|f| test_is_marked_broken(f).unwrap_or(false)),
+        };
+        let all_features_test_arch = match test_architecture("@")? {
+            Some(v) => v.to_owned(),
+            None => all_features
+                .iter()
+                .fold(HashSet::new(), |mut set, f| {
+                    if let Ok(Some(arch)) = test_architecture(f) {
+                        set.extend(arch.to_owned());
+                    }
+                    set
+                })
+                .into_iter()
+                .collect_vec(),
+        };
+        let all_features_test_arch: Vec<&str> =
+            all_features_test_arch.iter().map(AsRef::as_ref).collect();
+        let all_features_test_depends =
+            generate_test_dependencies("@", &all_features, config, &test_deps);
+        let mut testctl = io::BufWriter::new(file("tests/control")?);
+        write!(
+            testctl,
+            "{}",
+            PkgTest::new(
+                source.name(),
+                crate_name,
+                "@",
+                deb_upstream_version,
+                vec!["--all-features"],
+                &all_features_test_depends,
+                if all_features_test_broken {
+                    vec!["flaky"]
+                } else {
+                    vec![]
+                },
+                all_features_test_arch.deref(),
+            )?
+        )?;
+
+        // begin transforming dependencies
+        let working_features_with_deps = features_with_deps.clone();
+        let working_features_with_deps = {
+            let mut working_features_with_deps = working_features_with_deps;
+            // Detect corner case with feature naming regarding _ vs -.
+            // Debian does not support _ in package names. Cargo automatically
+            // converts - in crate names to _, but features (including optional
+            // dependencies) can have both _ and -.
+            let potential_corner_case = working_features_with_deps
+                .keys()
+                .filter(|x| base_deb_name(x).as_str() != **x)
+                .cloned()
+                .collect::<Vec<_>>();
+            for f in potential_corner_case {
+                let f_ = base_deb_name(f);
+                if let Some((df1, dd1)) = working_features_with_deps.remove(f_.as_str()) {
+                    // merge dependencies of f_ and f
+                    working_features_with_deps
+                        .entry(f)
+                        .and_modify(|(df0, dd0)| {
+                            let mut df = BTreeSet::from_iter(df0.drain(..));
+                            df.extend(df1);
+                            df.remove(f_.as_str());
+                            df.remove(f);
+                            let mut dd: HashSet<cargo::core::Dependency> =
+                                HashSet::from_iter(dd0.drain(..));
+                            dd.extend(dd1);
+                            df0.extend(df);
+                            dd0.extend(dd);
+                        });
+                    // go through other feature deps and change f_ to f
+                    for (_, (df, _)) in working_features_with_deps.iter_mut() {
+                        for feat in df.iter_mut() {
+                            if *feat == f_.as_str() {
+                                *feat = f;
+                            }
+                        }
+                    }
+                    // check we didn't create a cycle in features
+                    let dep_feats = traverse_depth(
+                        &|k: &&'static str| working_features_with_deps.get(k).map(|x| &x.0),
+                        f,
+                    );
+                    if dep_feats.contains(f) {
+                        log::debug!("transitive deps of feature {}: {:?}", f, dep_feats);
+                        debcargo_bail!(
+                            "Tried to merge features {} and {} as they are not representable separately\n\
+                             in Debian, but this resulted in a feature cycle. You need to manually patch the package.", f, f_);
+                    } else {
+                        debcargo_warn!(
+                            "Merged features {} and {} as they are not representable separately in Debian.\n\
+                             We checked that this does not break the package in an obvious way (feature cycle), however\n\
+                             if there is a more sophisticated breakage, you'll have to manually patch those \
+                             features instead.", f, f_);
+                    }
+                }
+            }
+            working_features_with_deps
+        };
+        log::trace!(
+            "working_features_with_deps: {:?}",
+            working_features_with_deps
+                .iter()
+                .map(|(&f, (ff, dd))| { (f, (ff, dd.iter().map(show_dep).collect::<Vec<_>>())) })
+                .collect::<Vec<_>>()
+        );
+        let (mut provides, reduced_features_with_deps) = if config.collapse_features {
+            collapse_features(working_features_with_deps)
+        } else {
+            reduce_provides(working_features_with_deps)
+        };
+        log::trace!(
+            "reduced_features_with_deps: {:?}",
+            reduced_features_with_deps
+                .iter()
+                .map(|(&f, (ff, dd))| { (f, (ff, dd.iter().map(show_dep).collect::<Vec<_>>())) })
+                .collect::<Vec<_>>()
+        );
+        // end transforming dependencies
+
+        log::trace!("provides: {:?}", provides);
+        let mut recommends = vec![];
+        let mut suggests = vec![];
+        for (&feature, features) in provides.iter() {
+            if feature.is_empty() {
+                continue;
+            } else if feature == "default" || features.contains(&"default") {
+                recommends.push(feature);
+            } else {
+                suggests.push(feature);
+            }
+        }
+
+        let mut no_features_edge_case = BTreeMap::new();
+        no_features_edge_case.insert("", (vec![], vec![]));
+        no_features_edge_case.insert("default", (vec![""], vec![]));
+        let no_features_edge_case = features_with_deps == no_features_edge_case;
+
+        for (feature, (f_deps, o_deps)) in reduced_features_with_deps.into_iter() {
+            let pk = PackageKey::feature(feature);
+            let f_provides = provides.remove(feature).unwrap();
+            let mut crate_features = f_provides.clone();
+            crate_features.push(feature);
+
+            let summary_suffix = if feature.is_empty() {
+                " - Rust source code".to_string()
+            } else {
+                match f_provides.len() {
+                    0 => format!(" - feature \"{}\"", feature),
+                    _ => format!(" - feature \"{}\" and {} more", feature, f_provides.len()),
+                }
+            };
+            let description_suffix = if feature.is_empty() {
+                format!("Source code for Debianized Rust crate \"{}\"", crate_name)
+            } else {
+                format!(
+                    "This metapackage enables feature \"{}\" for the \
+                     Rust {} crate, by pulling in any additional \
+                     dependencies needed by that feature.{}",
+                    feature,
+                    crate_name,
+                    match f_provides.len() {
+                        0 => "".to_string(),
+                        1 => format!(
+                            "\n\nAdditionally, this package also provides the \
+                             \"{}\" feature.",
+                            f_provides[0],
+                        ),
+                        _ => format!(
+                            "\n\nAdditionally, this package also provides the \
+                             \"{}\", and \"{}\" features.",
+                            f_provides[..f_provides.len() - 1].join("\", \""),
+                            f_provides[f_provides.len() - 1],
+                        ),
+                    },
+                )
+            };
+            let mut package = Package::new(
+                base_pkgname,
+                name_suffix,
+                crate_info.version(),
+                Description {
+                    prefix: summary_prefix.clone(),
+                    suffix: summary_suffix.clone(),
+                },
+                Description {
+                    prefix: description_prefix.clone(),
+                    suffix: description_suffix.clone(),
+                },
+                if feature.is_empty() {
+                    None
+                } else {
+                    Some(feature)
+                },
+                f_deps,
+                deb_deps(config.allow_prerelease_deps, &o_deps)?,
+                f_provides.clone(),
+                if feature.is_empty() {
+                    recommends.clone()
+                } else {
+                    vec![]
+                },
+                if feature.is_empty() {
+                    suggests.clone()
+                } else {
+                    vec![]
+                },
+            )?;
+            // If any overrides present for this package it will be taken care.
+            package.apply_overrides(config, pk, f_provides);
+
+            if package.summary_check_len().is_err() {
+                writeln!(
+                    control,
+                    concat!(
+                        "\n",
+                        "# FIXME (packages.\"(name)\".section) debcargo ",
+                        "auto-generated summary for {} is very long, consider overriding"
+                    ),
+                    package.name(),
+                )?;
+            }
+
+            write!(control, "\n{}", package)?;
+
+            // Override pointless overzealous warnings from lintian
+            if !feature.is_empty() {
+                let mut overrides =
+                    io::BufWriter::new(file(&format!("{}.lintian-overrides", package.name()))?);
+                write!(
+                    overrides,
+                    "{} binary: empty-rust-library-declares-provides *",
+                    package.name()
+                )?;
+            }
+
+            // Generate tests for all features in this package
+            if !no_features_edge_case {
+                for f in crate_features {
+                    let (feature_deps, _) = transitive_deps(&features_with_deps, f)?;
+
+                    // args
+                    let mut args = if f == "default" || feature_deps.contains(&"default") {
+                        vec![]
+                    } else {
+                        vec!["--no-default-features"]
+                    };
+                    // --features default sometimes fails, see
+                    // https://github.com/rust-lang/cargo/issues/8164
+                    if !f.is_empty() && f != "default" {
+                        args.push("--features");
+                        args.push(f);
+                    }
+
+                    // deps
+                    let test_depends =
+                        generate_test_dependencies(f, &feature_deps, config, &test_deps);
+                    let test_arch = match test_architecture(f)? {
+                        Some(v) => v.to_owned(),
+                        None => Vec::new(),
+                    };
+                    let test_arch: Vec<&str> = test_arch.iter().map(AsRef::as_ref).collect();
+                    let pkgtest = PkgTest::new(
+                        package.name(),
+                        crate_name,
+                        f,
+                        deb_upstream_version,
+                        args,
+                        &test_depends,
+                        if test_is_broken(f)? {
+                            vec!["flaky"]
+                        } else {
+                            vec![]
+                        },
+                        test_arch.deref(),
+                    )?;
+                    write!(testctl, "\n{}", pkgtest)?;
+                }
+            }
+        }
+        assert!(provides.is_empty());
+        // reduced_features_with_deps consumed by into_iter, no longer usable
+    }
+
+    if !bins.is_empty() {
+        // adding " - binaries" is a bit redundant for users, so just leave as-is
+        let summary_suffix = "".to_string();
+        let description_suffix = format!(
+            "This package contains the following binaries built from the Rust crate\n\"{}\":\n - {}",
+            crate_name,
+            bins.join("\n - ")
+        );
+
+        let mut bin_pkg = Package::new_bin(
+            bin_name,
+            name_suffix,
+            // if not-a-lib then Source section is already FIXME
+            if !lib {
+                None
+            } else {
+                Some("FIXME-(packages.\"(name)\".section)")
+            },
+            Description {
+                prefix: summary_prefix,
+                suffix: summary_suffix,
+            },
+            Description {
+                prefix: description_prefix,
+                suffix: description_suffix,
+            },
+        );
+
+        // Binary package overrides.
+        bin_pkg.apply_overrides(config, PackageKey::Bin, vec![]);
+        write!(control, "\n{}", bin_pkg)?;
+    }
+
+    Ok((source, has_dev_deps, test_is_broken("default")?))
+}
+
+fn generate_test_dependencies(
+    f: &str,
+    feature_deps: &[&str],
+    config: &Config,
+    test_deps: &[String],
+) -> Vec<String> {
+    Some(f)
+        .iter()
+        .chain(feature_deps)
+        .flat_map(|f| {
+            config
+                .package_test_depends(PackageKey::feature(f))
+                .into_iter()
+                .flatten()
+        })
+        .map(|s| s.to_string())
+        .chain(test_deps.to_owned())
+        .collect::<Vec<_>>()
+}
+
+fn collapse_features(
+    orig_features_with_deps: CrateDepInfo,
+) -> (BTreeMap<&'static str, Vec<&'static str>>, CrateDepInfo) {
+    let (provides, deps) = orig_features_with_deps.iter().fold(
+        (Vec::new(), Vec::new()),
+        |(mut provides, mut deps), (f, (_, f_deps))| {
+            if f != &"" {
+                provides.push(*f);
+            }
+            deps.append(&mut f_deps.clone());
+            (provides, deps)
+        },
+    );
+
+    let mut collapsed_provides = BTreeMap::new();
+    collapsed_provides.insert("", provides);
+
+    let mut collapsed_features_with_deps = BTreeMap::new();
+    collapsed_features_with_deps.insert("", (Vec::new(), deps));
+
+    (collapsed_provides, collapsed_features_with_deps)
+}
+
+/// Calculate Provides: in an attempt to reduce the number of binaries.
+///
+/// The algorithm is very simple and incomplete. e.g. it does not, yet
+/// simplify things like:
+///   f1 depends on f2, f3
+///   f2 depends on f4
+///   f3 depends on f4
+/// into
+///   f4 provides f1, f2, f3
+fn reduce_provides(
+    mut features_with_deps: CrateDepInfo,
+) -> (BTreeMap<&'static str, Vec<&'static str>>, CrateDepInfo) {
+    // If any features have duplicate dependencies, deduplicate them by
+    // making all the subsequent ones depend on the first one.
+    let mut features_rev_deps = HashMap::new();
+    for (&f, dep) in features_with_deps.iter() {
+        if !features_rev_deps.contains_key(dep) {
+            features_rev_deps.insert(dep.clone(), vec![]);
+        }
+        features_rev_deps.get_mut(dep).unwrap().push(f);
+    }
+    for (_, ff) in features_rev_deps.into_iter() {
+        let f0 = ff[0];
+        for f in &ff[1..] {
+            features_with_deps.insert(f, (vec![f0], vec![]));
+        }
+    }
+
+    // Calculate provides by following 0- or 1-length dependency lists.
+    let mut provides = BTreeMap::new();
+    let mut provided = Vec::new();
+    for (&f, (ref ff, ref dd)) in features_with_deps.iter() {
+        //debcargo_info!("provides considering: {:?}", &f);
+        if !dd.is_empty() {
+            continue;
+        }
+        assert!(!ff.is_empty() || f.is_empty());
+        let k = if ff.len() == 1 {
+            // if A depends on a single feature B, then B provides A.
+            ff[0]
+        } else {
+            continue;
+        };
+        //debcargo_info!("provides still considering: {:?}", &f);
+        if !provides.contains_key(k) {
+            provides.insert(k, vec![]);
+        }
+        provides.get_mut(k).unwrap().push(f);
+        provided.push(f);
+    }
+
+    //debcargo_info!("provides-internal: {:?}", &provides);
+    //debcargo_info!("provided-internal: {:?}", &provided);
+    for p in provided {
+        features_with_deps.remove(p);
+    }
+
+    let provides = features_with_deps
+        .keys()
+        .map(|k| {
+            (
+                *k,
+                traverse_depth(&|k: &&'static str| provides.get(k), k)
+                    .into_iter()
+                    .collect::<Vec<_>>(),
+            )
+        })
+        .collect::<BTreeMap<_, _>>();
+
+    (provides, features_with_deps)
+}
+
+pub(crate) fn toolchain_deps(min_rust_version: &Option<String>) -> Vec<String> {
+    let rustc = rustc_dep(min_rust_version, true);
+    // libstd-rust-dev here is needed to pick up the right arch variant for cross-builds!
+    ["cargo:native".into(), rustc, "libstd-rust-dev".into()].into()
+}
+
+fn rustc_dep(min_ver: &Option<String>, native: bool) -> String {
+    let native = if native { ":native" } else { "" };
+    if let Some(min_ver) = min_ver {
+        format!("rustc{native} (>= {min_ver})")
+    } else {
+        format!("rustc{native}")
+    }
+}
+
+fn changelog_or_new(tempdir: &Path) -> Result<(fs::File, String)> {
+    let mut changelog = fs::OpenOptions::new()
+        .read(true)
+        .write(true)
+        .create(true)
+        .truncate(false)
+        .open(tempdir.join("changelog"))?;
+    let mut changelog_data = String::new();
+    changelog.read_to_string(&mut changelog_data)?;
+    Ok((changelog, changelog_data))
+}
+
+fn changelog_first_last(tempdir: &Path) -> Result<(i32, i32)> {
+    let mut changelog = fs::File::open(tempdir.join("changelog"))?;
+    let mut changelog_data = String::new();
+    changelog.read_to_string(&mut changelog_data)?;
+    let mut last = None;
+    let mut first = None;
+    for x in ChangelogIterator::from(&changelog_data) {
+        let e = ChangelogEntry::from_str(x)?;
+        if last.is_none() {
+            last = Some(e.date.year());
+        }
+        first = Some(e.date.year());
+    }
+    if let Some(last) = last {
+        Ok((first.unwrap(), last))
+    } else {
+        Err(format_err!("changelog had no entries"))
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::rustc_dep;
+
+    #[test]
+    fn rustc_dep_includes_minver() {
+        assert_eq!(
+            "rustc:native (>= 1.65)",
+            rustc_dep(&Some("1.65".to_string()), true)
+        );
+    }
+
+    #[test]
+    fn rustc_dep_excludes_minver() {
+        assert_eq!("rustc:native", rustc_dep(&None, true));
+    }
+
+    #[test]
+    fn rustc_dep_includes_minver_autopkgtest() {
+        assert_eq!(
+            "rustc (>= 1.65)",
+            rustc_dep(&Some("1.65".to_string()), false)
+        );
+    }
+
+    #[test]
+    fn rustc_dep_excludes_minver_autopkgtest() {
+        assert_eq!("rustc", rustc_dep(&None, false));
+    }
+}
diff --git a/src/errors.rs b/src/errors.rs
new file mode 100644 (file)
index 0000000..d3b040c
--- /dev/null
@@ -0,0 +1,55 @@
+use anyhow;
+
+pub type Result<T> = std::result::Result<T, anyhow::Error>;
+pub use anyhow::format_err;
+
+#[macro_export]
+macro_rules! debcargo_info {
+    ($e:expr) => {
+        {
+            use ansi_term::Colour::Green;
+            eprintln!("{}", Green.paint($e));
+        }
+    };
+
+    ($fmt:expr, $( $arg:tt)+) => {
+        {
+            use ansi_term::Colour::Green;
+            let print_string = format!($fmt, $($arg)+);
+            eprintln!("{}", Green.paint(print_string));
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! debcargo_warn {
+    ($e:expr) => {
+        {
+            use ansi_term::Colour::RGB;
+            eprintln!("{}", RGB(255,165,0).bold().paint($e));
+        }
+    };
+
+    ($fmt:expr, $( $arg:tt)+) => {
+        {
+            use ansi_term::Colour::RGB;
+            let print_string = RGB(255,165,0).bold().paint(format!($fmt, $($arg)+));
+            eprintln!("{}", print_string);
+        }
+    };
+
+}
+
+#[macro_export]
+macro_rules! debcargo_bail {
+    ($e:expr) => {{
+        return Err(::anyhow::format_err!("{}", $e));
+    }};
+
+    ($fmt:expr, $( $arg:tt)+) => {
+        {
+            let error_string = format!($fmt, $($arg)+);
+            return Err(::anyhow::format_err!("{}", error_string));
+        }
+    };
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..b65073a
--- /dev/null
@@ -0,0 +1,11 @@
+#[macro_use]
+pub mod errors;
+pub mod cli;
+pub mod config;
+pub mod crates;
+pub mod debian;
+mod util;
+
+pub mod build_order;
+pub mod deb_dependencies;
+pub mod package;
diff --git a/src/package.rs b/src/package.rs
new file mode 100644 (file)
index 0000000..1f4362c
--- /dev/null
@@ -0,0 +1,262 @@
+use std::path::PathBuf;
+
+use anyhow::Context;
+
+use clap::{crate_version, Parser};
+
+use crate::config::{Config, PackageKey};
+use crate::crates::CrateInfo;
+use crate::debian::{self, DebInfo};
+use crate::errors::Result;
+use crate::util;
+
+pub struct PackageProcess {
+    // below state is filled in during init
+    pub crate_info: CrateInfo,
+    pub deb_info: DebInfo,
+    pub config_path: Option<PathBuf>,
+    pub config: Config,
+    // below state is filled in during the process
+    /// Output directory as specified by the user.
+    pub output_dir: Option<PathBuf>,
+    pub source_modified: Option<bool>,
+    /// Tempdir that contains a working copy of the eventual output.
+    pub temp_output_dir: Option<tempfile::TempDir>,
+    pub orig_tarball: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct PackageInitArgs {
+    /// Name of the crate to package.
+    pub crate_name: String,
+    /// Version of the crate to package; may contain dependency operators.
+    /// If empty string or omitted, resolves to the latest version.
+    pub version: Option<String>,
+    /// TOML file providing package-specific options.
+    #[arg(long)]
+    pub config: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct PackageExtractArgs {
+    /// Output directory for the package. The orig tarball is named according
+    /// to Debian conventions in the parent directory of this directory.
+    #[arg(long)]
+    pub directory: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Parser)]
+pub struct PackageExecuteArgs {
+    /// Assume the changelog is already bumped, and leave it alone.
+    #[arg(long)]
+    pub changelog_ready: bool,
+    /// Guess extra values for d/copyright. Might be slow.
+    #[arg(long)]
+    pub copyright_guess_harder: bool,
+    /// Don't write back hint files or d/changelog to the source overlay directory.
+    #[arg(long)]
+    pub no_overlay_write_back: bool,
+}
+
+impl PackageProcess {
+    /// More fine-grained access. For normal usage see `Self::init` instead.
+    pub fn new(
+        mut crate_info: CrateInfo,
+        config_path: Option<PathBuf>,
+        config: Config,
+    ) -> Result<Self> {
+        crate_info.set_includes_excludes(config.orig_tar_excludes(), config.orig_tar_whitelist());
+        let deb_info = DebInfo::new(&crate_info, crate_version!(), config.semver_suffix);
+
+        Ok(Self {
+            crate_info,
+            deb_info,
+            config_path,
+            config,
+            output_dir: None,
+            source_modified: None,
+            temp_output_dir: None,
+            orig_tarball: None,
+        })
+    }
+
+    pub fn init(init_args: PackageInitArgs) -> Result<Self> {
+        let crate_name = &init_args.crate_name;
+        let version = init_args.version.as_deref();
+        let config = init_args.config;
+
+        let (config_path, config) = match config {
+            Some(path) => {
+                let config = Config::parse(&path).context("failed to parse debcargo.toml")?;
+                (Some(path), config)
+            }
+            None => (None, Config::default()),
+        };
+
+        let crate_path = config.crate_src_path(config_path.as_deref());
+        let crate_info = match crate_path {
+            Some(p) => CrateInfo::new_with_local_crate(crate_name, version, &p)?,
+            None => CrateInfo::new(crate_name, version)?,
+        };
+
+        Self::new(crate_info, config_path, config)
+    }
+
+    pub fn extract(&mut self, extract: PackageExtractArgs) -> Result<()> {
+        assert!(self.output_dir.is_none());
+        assert!(self.source_modified.is_none());
+        let Self {
+            crate_info,
+            deb_info,
+            ..
+        } = self;
+        // vars read; begin stage
+
+        let output_dir = extract
+            .directory
+            .unwrap_or_else(|| deb_info.package_source_dir().to_path_buf());
+
+        let source_modified = crate_info.extract_crate(&output_dir)?;
+
+        // stage finished; set vars
+        self.output_dir = Some(output_dir);
+        self.source_modified = Some(source_modified);
+        Ok(())
+    }
+
+    pub fn apply_overrides(&mut self) -> Result<()> {
+        assert!(self.temp_output_dir.is_none());
+        let Self {
+            crate_info,
+            config_path,
+            config,
+            output_dir,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        // vars read; begin stage
+
+        let temp_output_dir = debian::apply_overlay_and_patches(
+            crate_info,
+            config_path.as_deref(),
+            config,
+            output_dir,
+        )?;
+
+        // stage finished; set vars
+        self.temp_output_dir = Some(temp_output_dir);
+        Ok(())
+    }
+
+    pub fn prepare_orig_tarball(&mut self) -> Result<()> {
+        assert!(self.orig_tarball.is_none());
+        let Self {
+            crate_info,
+            deb_info,
+            output_dir,
+            source_modified,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        let source_modified = source_modified.as_ref().unwrap();
+        // vars read; begin stage
+
+        let orig_tarball = output_dir
+            .parent()
+            .unwrap()
+            .join(deb_info.orig_tarball_path());
+        debian::prepare_orig_tarball(crate_info, &orig_tarball, *source_modified, output_dir)?;
+
+        // stage finished; set vars
+        self.orig_tarball = Some(orig_tarball);
+        Ok(())
+    }
+
+    pub fn prepare_debian_folder(&mut self, args: PackageExecuteArgs) -> Result<()> {
+        let Self {
+            crate_info,
+            deb_info,
+            config_path,
+            config,
+            output_dir,
+            temp_output_dir,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        let temp_output_dir = temp_output_dir.as_ref().unwrap();
+        // vars read; begin stage
+
+        debian::prepare_debian_folder(
+            crate_info,
+            deb_info,
+            config_path.as_deref(),
+            config,
+            output_dir,
+            temp_output_dir,
+            args.changelog_ready,
+            args.copyright_guess_harder,
+            !args.no_overlay_write_back,
+        )?;
+
+        // stage finished; set vars
+        Ok(())
+    }
+
+    pub fn post_package_checks(&self) -> Result<()> {
+        let Self {
+            config_path,
+            config,
+            output_dir,
+            orig_tarball,
+            ..
+        } = self;
+        let output_dir = output_dir.as_ref().unwrap();
+        let orig_tarball = orig_tarball.as_ref().unwrap();
+
+        let curdir = std::env::current_dir()?;
+        debcargo_info!(
+            concat!("Package Source: {}\n", "Original Tarball for package: {}\n"),
+            util::rel_p(output_dir, &curdir),
+            util::rel_p(orig_tarball, &curdir)
+        );
+        let fixmes = util::lookup_fixmes(output_dir)?;
+        if !fixmes.is_empty() {
+            debcargo_warn!("FIXME found in the following files.");
+            for f in fixmes {
+                if util::hint_file_for(&f).is_some() {
+                    debcargo_warn!("\t(•) {}", util::rel_p(&f, &curdir));
+                } else {
+                    debcargo_warn!("\t •  {}", util::rel_p(&f, &curdir));
+                }
+            }
+            debcargo_warn!("");
+            debcargo_warn!("To fix, try combinations of the following: ");
+            match config_path.as_deref() {
+                None => debcargo_warn!("\t •  Write a config file and use it with --config"),
+                Some(c) => {
+                    debcargo_warn!("\t •  Add or edit overrides in your config file:");
+                    debcargo_warn!("\t    {}", util::rel_p(c, &curdir));
+                }
+            };
+            match config.overlay_dir(config_path.as_deref()) {
+                None => debcargo_warn!("\t •  Create an overlay directory and add it to your config file with overlay = \"/path/to/overlay\""),
+                Some(p) => {
+                    debcargo_warn!("\t •  Add or edit files in your overlay directory:");
+                    debcargo_warn!("\t    {}", util::rel_p(&p, &curdir));
+                }
+            }
+        }
+        if let Some(architecture) = self.config.package_architecture(PackageKey::BareLib) {
+            if architecture == &vec!["all"] {
+                debcargo_warn!("");
+                debcargo_warn!(
+                    "'Architecture: all' override found for library package. This potentially breaks Multi-Arch,"
+                );
+                debcargo_warn!(
+                    "see https://rust-team.pages.debian.net/book/policy.html#why-architecture-any."
+                );
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/src/util.rs b/src/util.rs
new file mode 100644 (file)
index 0000000..0c2798f
--- /dev/null
@@ -0,0 +1,287 @@
+use std::borrow::Cow;
+use std::collections::{BTreeMap, BTreeSet, VecDeque};
+use std::ffi::OsStr;
+use std::fmt;
+use std::fs;
+use std::io::{BufRead, BufReader, Error};
+use std::iter::Iterator;
+#[cfg(unix)]
+use std::os::unix::ffi::OsStrExt;
+#[cfg(unix)]
+use std::os::unix::fs::symlink;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+use anyhow::bail;
+use itertools::Itertools;
+use walkdir::WalkDir;
+
+pub const HINT_SUFFIX: &str = ".debcargo.hint";
+
+#[cfg(unix)]
+pub fn hint_file_for(file: &Path) -> Option<Cow<'_, Path>> {
+    let file = file.as_os_str().as_bytes();
+    if file.len() >= HINT_SUFFIX.len()
+        && &file[file.len() - HINT_SUFFIX.len()..] == HINT_SUFFIX.as_bytes()
+    {
+        Some(Cow::Borrowed(Path::new(OsStr::from_bytes(
+            &file[..file.len() - HINT_SUFFIX.len()],
+        ))))
+    } else {
+        None
+    }
+}
+
+#[cfg(not(unix))]
+pub fn hint_file_for(file: &Path) -> Option<Cow<'_, Path>> {
+    if let Some(file_str) = file.to_str() {
+        if file_str.ends_with(HINT_SUFFIX) {
+            let trimmed_path = &file_str[..file_str.len() - HINT_SUFFIX.len()];
+            Some(Cow::Owned(PathBuf::from(trimmed_path)))
+        } else {
+            None
+        }
+    } else {
+        // Handle the case where the path is not representable as a string
+        None
+    }
+}
+
+pub fn lookup_fixmes(srcdir: &Path) -> Result<BTreeSet<PathBuf>, Error> {
+    let mut fixmes = BTreeSet::new();
+    let debiandir = srcdir.join("debian");
+    for entry in WalkDir::new(debiandir) {
+        let entry = entry?;
+        if entry.file_type().is_file() {
+            let file = fs::File::open(entry.path())?;
+            let reader = BufReader::new(file);
+            // If we find one FIXME we break the loop and check next file. Idea
+            // is only to find files with FIXME strings in it.
+            for line in reader.lines() {
+                match line {
+                    Ok(line_content) => {
+                        if line_content.contains("FIXME") {
+                            fixmes.insert(entry.path().to_path_buf());
+                            break;
+                        }
+                    }
+                    Err(e) => {
+                        debcargo_warn!(
+                            "Warning: Could not check for FIXMEs in file {:?}: {}",
+                            rel_p(entry.path(), srcdir),
+                            e
+                        );
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    // ignore hint files whose non-hint partners exists and don't have a FIXME
+    let fixmes = fixmes
+        .iter()
+        .filter(|f| match hint_file_for(f) {
+            Some(ff) => fixmes.contains(ff.as_ref()) || !ff.exists(),
+            None => true,
+        })
+        .cloned()
+        .collect::<BTreeSet<_>>();
+    Ok(fixmes)
+}
+
+pub fn rel_p<'a>(path: &'a Path, base: &'a Path) -> Cow<'a, str> {
+    path.strip_prefix(base).unwrap_or(path).to_string_lossy()
+}
+
+pub fn copy_tree(oldtree: &Path, newtree: &Path) -> Result<(), Error> {
+    for entry in WalkDir::new(oldtree) {
+        let entry = entry?;
+        if entry.depth() == 0 {
+            continue;
+        }
+        let oldpath = entry.path();
+        let newpath = newtree.join(oldpath.strip_prefix(oldtree).unwrap());
+        let ftype = entry.file_type();
+        match ftype {
+            f if f.is_dir() => {
+                fs::create_dir(newpath)?;
+            }
+            f if f.is_file() => {
+                fs::copy(oldpath, newpath)?;
+            }
+            #[cfg(unix)]
+            f if f.is_symlink() => {
+                symlink(fs::read_link(oldpath)?, newpath)?;
+            }
+            _ => {}
+        }
+    }
+    Ok(())
+}
+
+pub fn show_vec_with<'a, T, F>(it: impl IntoIterator<Item = &'a T>, f: F) -> String
+where
+    T: 'a,
+    F: FnMut(&T) -> String,
+{
+    Itertools::intersperse(it.into_iter().map(f), ", ".to_string()).collect::<String>()
+}
+
+pub fn show_vec<'a, T>(it: impl IntoIterator<Item = &'a T>) -> String
+where
+    T: fmt::Display + 'a,
+{
+    show_vec_with(it, std::string::ToString::to_string)
+}
+
+pub fn expect_success(cmd: &mut Command, err: &str) -> Result<(), anyhow::Error> {
+    match cmd.status() {
+        Ok(status) if status.success() => Ok(()),
+        Ok(_) => bail!("{}", err),
+        Err(e) => bail!("{}\n{}", err, e),
+    }
+}
+
+pub(crate) fn traverse_depth<'a, V, F>(succ: &'a F, key: V) -> BTreeSet<V>
+where
+    V: Ord + Copy + 'a,
+    F: Fn(&V) -> Option<&'a Vec<V>>,
+{
+    let mut remain = VecDeque::from_iter([key]);
+    let mut seen = BTreeSet::new();
+    while let Some(v) = remain.pop_front() {
+        for v_ in succ(&v).into_iter().flatten() {
+            if !seen.contains(v_) {
+                seen.insert(*v_);
+                remain.push_back(*v_);
+            }
+        }
+    }
+    seen
+}
+
+/// Get a value that might be set at a key or any of its ancestor keys,
+/// whichever is closest. Error if there are conflicting definitions.
+#[allow(clippy::type_complexity)]
+pub(crate) fn get_transitive_val<
+    'a,
+    P: Fn(K) -> Option<&'a Vec<K>>,
+    F: Fn(K) -> Option<V>,
+    K: 'a + Ord + Copy,
+    V: Eq + Ord,
+>(
+    getparents: &'a P,
+    f: &F,
+    key: K,
+) -> Result<Option<V>, (K, Vec<(K, V)>)> {
+    let here = f(key);
+    if here.is_some() {
+        // value overrides anything from parents
+        Ok(here)
+    } else {
+        let mut candidates = Vec::new();
+        for par in getparents(key).into_iter().flatten() {
+            if let Some(v) = get_transitive_val(getparents, f, *par)? {
+                candidates.push((*par, v))
+            }
+        }
+        if candidates.is_empty() {
+            Ok(None) // here is None
+        } else {
+            let mut values = candidates.iter().map(|(_, v)| v).collect::<Vec<_>>();
+            values.sort();
+            values.dedup();
+            if values.len() == 1 {
+                Ok(candidates.pop().map(|(_, v)| v))
+            } else {
+                Err((key, candidates)) // handle conflict
+            }
+        }
+    }
+}
+
+pub fn graph_from_succ<V, FV, FL, E>(
+    seed: impl IntoIterator<Item = V>,
+    succ: &mut FV,
+    log: &mut FL,
+) -> Result<BTreeMap<V, BTreeSet<V>>, E>
+where
+    V: Ord + Clone,
+    FV: FnMut(&V) -> Result<(Vec<V>, Vec<V>), E>,
+    FL: FnMut(&VecDeque<V>, &BTreeMap<V, BTreeSet<V>>) -> Result<(), E>,
+{
+    let mut seen = BTreeSet::from_iter(seed);
+    let mut graph = BTreeMap::new();
+    let mut remain = VecDeque::from_iter(seen.iter().cloned());
+    while let Some(v) = remain.pop_front() {
+        log(&remain, &graph)?;
+        let (hard, soft) = succ(&v)?;
+        for v_ in hard.iter().chain(soft.iter()) {
+            if !seen.contains(v_) {
+                seen.insert(v_.clone());
+                remain.push_back(v_.clone());
+            }
+        }
+        graph.insert(v, BTreeSet::from_iter(hard));
+    }
+    Ok(graph)
+}
+
+pub fn succ_proj<S, T, F>(succ: &BTreeMap<S, BTreeSet<S>>, proj: F) -> BTreeMap<T, BTreeSet<T>>
+where
+    F: Fn(&S) -> T,
+    S: Ord,
+    T: Ord + Clone,
+{
+    let mut succ_proj: BTreeMap<T, BTreeSet<T>> = BTreeMap::new();
+    for (s, ss) in succ {
+        let e = succ_proj.entry(proj(s)).or_default();
+        for s_ in ss {
+            e.insert(proj(s_));
+        }
+    }
+    succ_proj
+}
+
+pub fn succ_to_pred<V>(succ: &BTreeMap<V, BTreeSet<V>>) -> BTreeMap<V, BTreeSet<V>>
+where
+    V: Ord + Clone,
+{
+    let mut pred: BTreeMap<V, BTreeSet<V>> = BTreeMap::new();
+    for (v, vv) in succ {
+        for v_ in vv {
+            pred.entry(v_.clone()).or_default().insert(v.clone());
+        }
+    }
+    pred
+}
+
+pub fn topo_sort<V>(
+    seed: impl IntoIterator<Item = V>,
+    succ: BTreeMap<V, BTreeSet<V>>,
+    mut pred: BTreeMap<V, BTreeSet<V>>,
+) -> Result<Vec<V>, BTreeMap<V, BTreeSet<V>>>
+where
+    V: Ord + Clone,
+{
+    let empty = BTreeSet::new();
+    let mut remain = VecDeque::from_iter(seed);
+    let mut sort = Vec::new();
+    while let Some(v) = remain.pop_front() {
+        sort.push(v.clone());
+        for v_ in succ.get(&v).unwrap_or(&empty) {
+            let par = pred.entry(v_.clone()).or_default();
+            par.remove(&v);
+            if par.is_empty() {
+                remain.push_back(v_.clone());
+            }
+        }
+    }
+    pred.retain(|_, v| !v.is_empty());
+    if !pred.is_empty() {
+        Err(pred)
+    } else {
+        Ok(sort)
+    }
+}
diff --git a/tests/clap_override.toml b/tests/clap_override.toml
new file mode 100644 (file)
index 0000000..8595e84
--- /dev/null
@@ -0,0 +1,17 @@
+uploaders = ["Sylvestre Ledru <sylvestre@debian.org>", "Ximin Luo <infinity0@debian.org>" ]
+
+[source]
+policy = "4.0.0"
+homepage = "https://clap.rs"
+
+[packages.lib]
+summary = "Simple, efficient and full featured Command line argument parser - source"
+description = """
+clap is used to parse and validate string of command line arguments provided by
+user at runtime. It provides help and version flags by default and additionally
+provide help subcommands in addition to traditional flags.
+This package provides clap with following default features.
+ * suggestions: provides did you mean suggestions on typos
+ * color: turns on colored error messages.
+ * wrap_help: Wrap the help at actual terminal width when available.
+"""
diff --git a/tests/config_tests.rs b/tests/config_tests.rs
new file mode 100644 (file)
index 0000000..0813771
--- /dev/null
@@ -0,0 +1,197 @@
+extern crate debcargo;
+
+use debcargo::config::{Config, PackageKey};
+use std::path::Path;
+
+#[test]
+fn source_package_override() {
+    let filepath = Path::new("tests/clap_override.toml");
+
+    let config = Config::parse(filepath);
+    assert!(config.is_ok());
+
+    let config = config.unwrap();
+
+    assert!(config.source.is_some());
+    assert_eq!(config.packages.len(), 1);
+
+    let policy = config.policy_version();
+    assert!(policy.is_some());
+    assert_eq!(policy.unwrap(), "4.0.0");
+
+    let homepage = config.homepage();
+    assert!(homepage.is_some());
+    assert_eq!(homepage.unwrap(), "https://clap.rs");
+
+    assert!(config.section().is_none());
+    assert!(config.build_depends().is_none());
+
+    let filepath = Path::new("tests/debcargo_override.toml");
+    let config = Config::parse(filepath);
+    assert!(config.is_ok());
+
+    let config = config.unwrap();
+
+    assert!(config.source.is_some());
+
+    let section = config.section();
+    assert!(section.is_some());
+    assert_eq!(section.unwrap(), "rust");
+
+    assert_eq!(config.packages.len(), 1);
+    let sd = config.package_summary(PackageKey::Bin);
+    assert!(sd.is_some());
+
+    if let Some(s) = sd {
+        assert_eq!(s, "Tool to create Debian package from Rust crate");
+    }
+
+    let sd = config.package_description(PackageKey::Bin);
+    assert!(sd.is_some());
+    if let Some(d) = sd {
+        assert_eq!(
+            d,
+            "\
+This package provides debcargo a tool to create Debian source package from \
+                    Rust
+crate. The package created by this tool is as per the packaging policy \
+                    set by
+Debian Rust team.
+"
+        );
+    }
+}
+
+#[test]
+fn binary_package_override() {
+    let filepath = Path::new("tests/tiny-dfr_override.toml");
+    let config = Config::parse(filepath);
+    assert!(config.is_ok());
+
+    let config = config.unwrap();
+
+    assert_eq!(config.packages.len(), 1);
+
+    assert_eq!(
+        config.package_summary(PackageKey::Bin),
+        Some("dynamic touch bar daemon")
+    );
+
+    assert_eq!(
+        config.package_description(PackageKey::Bin),
+        Some(
+            "\
+    This package contains tiny-dfr, the userland touch bar daemon.
+
+tiny-dfr shows the function row and media control keys (brightness,
+volume, backlight, play, etc) on your touch bar. Currently supported
+platforms are Apple Silicon and T2 Macs.
+"
+        )
+    );
+
+    assert_eq!(
+        config.package_architecture(PackageKey::Bin),
+        Some(&vec!["arm64".to_string(), "amd64".to_string()])
+    );
+}
+
+#[test]
+fn sd_top_level() {
+    let filepath = Path::new("tests/debcargo_override_top_level.toml");
+    let config = Config::parse(filepath);
+    assert!(config.is_ok());
+
+    let config = config.unwrap();
+
+    assert!(config.source.is_some());
+
+    let section = config.section();
+    assert!(section.is_some());
+    assert_eq!(section.unwrap(), "rust");
+
+    assert_eq!(
+        config.summary.unwrap(),
+        "Tool to create Debian package from Rust crate"
+    );
+    assert_eq!(
+        config.description.unwrap(),
+        "\
+This package provides debcargo a tool to create Debian source package from \
+                    Rust
+crate. The package created by this tool is as per the packaging policy \
+                    set by
+Debian Rust team.
+"
+    );
+}
+
+#[test]
+fn unknown_fields_captured_with_warning() {
+    use std::fs::File;
+    use std::io::Write;
+    use tempfile::tempdir;
+
+    let dir = tempdir().unwrap();
+    let file_path = dir.path().join("test_debcargo.toml");
+
+    // Test unknown field at top level
+    let mut file = File::create(&file_path).unwrap();
+    writeln!(
+        file,
+        r#"
+semver_suffix = true
+overlay = "."
+verlay = "typo"  # This should be captured as an unknown field
+"#
+    )
+    .unwrap();
+    drop(file);
+
+    let result = Config::parse(&file_path);
+    assert!(result.is_ok());
+    let config = result.unwrap();
+    assert!(config.unknown_fields.contains_key("verlay"));
+
+    // Test unknown field in source section
+    let mut file = File::create(&file_path).unwrap();
+    writeln!(
+        file,
+        r#"
+[source]
+section = "rust"
+unknown_field = "value"
+"#
+    )
+    .unwrap();
+    drop(file);
+
+    let result = Config::parse(&file_path);
+    assert!(result.is_ok());
+    let config = result.unwrap();
+    assert!(config.source.is_some());
+    if let Some(source) = config.source {
+        assert!(source.unknown_fields.contains_key("unknown_field"));
+    }
+
+    // Test unknown field in packages section
+    let mut file = File::create(&file_path).unwrap();
+    writeln!(
+        file,
+        r#"
+[packages.lib]
+section = "libs"
+unknwon_field = "value"
+"#
+    )
+    .unwrap();
+    drop(file);
+
+    let result = Config::parse(&file_path);
+    assert!(result.is_ok());
+    let config = result.unwrap();
+    assert!(config.packages.contains_key("lib"));
+    if let Some(lib_package) = config.packages.get("lib") {
+        assert!(lib_package.unknown_fields.contains_key("unknwon_field"));
+    }
+}
diff --git a/tests/configs/aesni-0.10/debian/debcargo.toml b/tests/configs/aesni-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/aesni-0.10/debian/rules b/tests/configs/aesni-0.10/debian/rules
new file mode 100644 (file)
index 0000000..083418e
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate requires builder to set custom RUSTFLAGS
+# we can't do that in Debian due to architecture baselines
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/aesni/debian/debcargo.toml b/tests/configs/aesni/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/aesni/debian/rules b/tests/configs/aesni/debian/rules
new file mode 100644 (file)
index 0000000..083418e
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate requires builder to set custom RUSTFLAGS
+# we can't do that in Debian due to architecture baselines
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/afl-0.10/debian/debcargo.toml b/tests/configs/afl-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..c30d237
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "lld", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "llvm", "lld", "clang"]
diff --git a/tests/configs/afl-0.10/debian/rules b/tests/configs/afl-0.10/debian/rules
new file mode 100644 (file)
index 0000000..5f52057
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+# needed by build script
+export XDG_DATA_HOME := $(CURDIR)/debian/xdg-data-home
+export CXXFLAGS := -Wno-unused-command-line-argument
+export CFLAGS := -Wno-unused-command-line-argument
+
+override_dh_strip_nondeterminism:
+       # dh_strip_nondeterminism can't parse these files
+       rm -rf $(CURDIR)/debian/libruzt-afl-*-dev/usr/share/cargo/registry/afl-*/AFLplusplus/docs/vuln_samples
+       dh_strip_nondeterminism
diff --git a/tests/configs/afl-0.13/debian/debcargo.toml b/tests/configs/afl-0.13/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/afl-0.13/debian/rules b/tests/configs/afl-0.13/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/aom-sys-0.3/debian/debcargo.toml b/tests/configs/aom-sys-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..3c5afd9
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libaom-dev"]
diff --git a/tests/configs/ascii-0.8/debian/debcargo.toml b/tests/configs/ascii-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/ascii-0.8/debian/patches/fix-old-dep.patch b/tests/configs/ascii-0.8/debian/patches/fix-old-dep.patch
new file mode 100644 (file)
index 0000000..3aa27b5
--- /dev/null
@@ -0,0 +1,20 @@
+Crate authors like to put dev-dependencies in dependencies due to
+https://github.com/rust-lang/cargo/issues/1596
+
+Then due to lack of maintenance this pollutes the dependency set with old
+crates that no longer compile.
+
+Here, quickcheck 0.4 eventually depends on simd which no longer compiles.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -22,9 +22,6 @@
+ [[test]]
+ name = "tests"
+ path = "tests.rs"
+-[dependencies.quickcheck]
+-version = "0.4.1"
+-optional = true
+ [features]
+ default = ["std"]
diff --git a/tests/configs/ascii-0.8/debian/patches/series b/tests/configs/ascii-0.8/debian/patches/series
new file mode 100644 (file)
index 0000000..f385166
--- /dev/null
@@ -0,0 +1 @@
+fix-old-dep.patch
diff --git a/tests/configs/aws-lc-fips-sys-0.12/debian/debcargo.toml b/tests/configs/aws-lc-fips-sys-0.12/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..16cd04f
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["golang"]
diff --git a/tests/configs/aws-lc-fips-sys-0.12/debian/rules b/tests/configs/aws-lc-fips-sys-0.12/debian/rules
new file mode 100644 (file)
index 0000000..7dd2db7
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# requires writable dir
+override_dh_auto_test:
+       dh_auto_test || true
+
diff --git a/tests/configs/blas-src-0.6/debian/debcargo.toml b/tests/configs/blas-src-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/blas-src-0.6/debian/patches/drop-accelerate.diff b/tests/configs/blas-src-0.6/debian/patches/drop-accelerate.diff
new file mode 100644 (file)
index 0000000..a2ba0b1
--- /dev/null
@@ -0,0 +1,22 @@
+Index: blas-src-0.6.1/Cargo.toml
+===================================================================
+--- blas-src-0.6.1.orig/Cargo.toml
++++ blas-src-0.6.1/Cargo.toml
+@@ -22,9 +22,6 @@ keywords = ["linear-algebra"]
+ categories = ["science"]
+ license = "Apache-2.0/MIT"
+ repository = "https://github.com/blas-lapack-rs/blas-src"
+-[dependencies.accelerate-src]
+-version = "0.3"
+-optional = true
+ [dependencies.intel-mkl-src]
+ version = "0.5"
+@@ -39,7 +36,6 @@ version = "0.9"
+ optional = true
+ [features]
+-accelerate = ["accelerate-src"]
+ intel-mkl = ["intel-mkl-src"]
+ netlib = ["netlib-src"]
+ openblas = ["openblas-src"]
diff --git a/tests/configs/blas-src-0.6/debian/patches/series b/tests/configs/blas-src-0.6/debian/patches/series
new file mode 100644 (file)
index 0000000..c52a8c3
--- /dev/null
@@ -0,0 +1 @@
+drop-accelerate.diff
diff --git a/tests/configs/broken-dh-strip/debian/debcargo.toml b/tests/configs/broken-dh-strip/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/broken-dh-strip/debian/rules b/tests/configs/broken-dh-strip/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/broken-lto/debian/debcargo.toml b/tests/configs/broken-lto/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/broken-lto/debian/rules b/tests/configs/broken-lto/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/broken-upstream/debian/debcargo.toml b/tests/configs/broken-upstream/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/broken-upstream/debian/rules b/tests/configs/broken-upstream/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/brotli-decompressor-2/debian/debcargo.toml b/tests/configs/brotli-decompressor-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/brotli-decompressor-2/debian/rules b/tests/configs/brotli-decompressor-2/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/clang-sys-0.23/debian/debcargo.toml b/tests/configs/clang-sys-0.23/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clang-sys-0.26/debian/debcargo.toml b/tests/configs/clang-sys-0.26/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clang-sys-1/debian/debcargo.toml b/tests/configs/clang-sys-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clang-sys/debian/debcargo.toml b/tests/configs/clang-sys/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..583dcce
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = ["llvm", "clang"]
+
+[packages.lib]
+depends = ["libclang-dev", "lld", "clang"]
diff --git a/tests/configs/clippy-0.0/debian/debcargo.toml b/tests/configs/clippy-0.0/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/clippy-0.0/debian/rules b/tests/configs/clippy-0.0/debian/rules
new file mode 100644 (file)
index 0000000..b2056b4
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# clippy upstream now errors on purpose with the message "clippy is no longer
+# available on crates.io". Many old crates depend on clippy even though it is
+# a dev-dependency because of [3] and there are far too many to patch. So just
+# make the build of clippy "succeed"; it does not actually get used in the
+# build of a reverse-dependency anyway.
+#
+# [1] https://github.com/rust-lang/cargo/issues/1596
+
+override_dh_auto_test:
+       dh_auto_test || true
+
+override_dh_auto_install:
+       dh_auto_install || true
diff --git a/tests/configs/cmake-0.1/debian/debcargo.toml b/tests/configs/cmake-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..79ca598
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["cmake"]
diff --git a/tests/configs/compiler-builtins-0.1/debian/debcargo.toml b/tests/configs/compiler-builtins-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/compiler-builtins-0.1/debian/rules b/tests/configs/compiler-builtins-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/compiler-error-0.1/debian/debcargo.toml b/tests/configs/compiler-error-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/compiler-error-0.1/debian/rules b/tests/configs/compiler-error-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/compiletest-rs-0.3/debian/debcargo.toml b/tests/configs/compiletest-rs-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/compiletest-rs-0.3/debian/rules b/tests/configs/compiletest-rs-0.3/debian/rules
new file mode 100644 (file)
index 0000000..8ad6a55
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate errors on the default feature by design
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/core-arch-0.1/debian/debcargo.toml b/tests/configs/core-arch-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-arch-0.1/debian/rules b/tests/configs/core-arch-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/core-error-0.0/debian/debcargo.toml b/tests/configs/core-error-0.0/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-error-0.0/debian/rules b/tests/configs/core-error-0.0/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/core-extensions-0.1/debian/debcargo.toml b/tests/configs/core-extensions-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-extensions-0.1/debian/rules b/tests/configs/core-extensions-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/core-foundation-0.9/debian/debcargo.toml b/tests/configs/core-foundation-0.9/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-foundation-0.9/debian/rules b/tests/configs/core-foundation-0.9/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/core-graphics-0.23/debian/debcargo.toml b/tests/configs/core-graphics-0.23/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-graphics-0.23/debian/rules b/tests/configs/core-graphics-0.23/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/core-graphics-types-0.1/debian/debcargo.toml b/tests/configs/core-graphics-types-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-graphics-types-0.1/debian/rules b/tests/configs/core-graphics-types-0.1/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/core-text-20/debian/debcargo.toml b/tests/configs/core-text-20/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/core-text-20/debian/rules b/tests/configs/core-text-20/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/cpp-demangle-0.3/debian/debcargo.toml b/tests/configs/cpp-demangle-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..7591b7f
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+bin = false
diff --git a/tests/configs/dav1d-sys-0.3/debian/debcargo.toml b/tests/configs/dav1d-sys-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..848a089
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libdav1d-dev"]
diff --git a/tests/configs/dav1d-sys-0.3/debian/patches/relax-bindgen.patch b/tests/configs/dav1d-sys-0.3/debian/patches/relax-bindgen.patch
new file mode 100644 (file)
index 0000000..9874749
--- /dev/null
@@ -0,0 +1,13 @@
+Index: dav1d-sys-0.3.5/Cargo.toml
+===================================================================
+--- dav1d-sys-0.3.5.orig/Cargo.toml
++++ dav1d-sys-0.3.5/Cargo.toml
+@@ -24,7 +24,7 @@ dav1d = "0.9.0"
+ [dependencies]
+ [build-dependencies.bindgen]
+-version = "0.59.1"
++version = "0.66"
+ [build-dependencies.system-deps]
+ version = "6.0"
diff --git a/tests/configs/dav1d-sys-0.3/debian/patches/series b/tests/configs/dav1d-sys-0.3/debian/patches/series
new file mode 100644 (file)
index 0000000..49c3558
--- /dev/null
@@ -0,0 +1 @@
+relax-bindgen.patch
diff --git a/tests/configs/dav1d-sys-0.8/debian/debcargo.toml b/tests/configs/dav1d-sys-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..848a089
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libdav1d-dev"]
diff --git a/tests/configs/derive-builder-0.9/debian/debcargo.toml b/tests/configs/derive-builder-0.9/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/derive-builder-0.9/debian/rules b/tests/configs/derive-builder-0.9/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/diesel-1/debian/debcargo.toml b/tests/configs/diesel-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/diesel-1/debian/patches/fix-old-dep.patch b/tests/configs/diesel-1/debian/patches/fix-old-dep.patch
new file mode 100644 (file)
index 0000000..79a0a39
--- /dev/null
@@ -0,0 +1,21 @@
+Crate authors like to put dev-dependencies in dependencies due to
+https://github.com/rust-lang/cargo/issues/1596
+
+Then due to lack of maintenance this pollutes the dependency set with old
+crates that no longer compile.
+
+Here, quickcheck 0.4 eventually depends on simd which no longer compiles.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -76,10 +76,6 @@
+ version = ">=0.3.0, <0.5.0"
+ optional = true
+-[dependencies.quickcheck]
+-version = "0.4"
+-optional = true
+-
+ [dependencies.r2d2]
+ version = ">= 0.8, < 0.9"
+ optional = true
diff --git a/tests/configs/diesel-1/debian/patches/series b/tests/configs/diesel-1/debian/patches/series
new file mode 100644 (file)
index 0000000..f385166
--- /dev/null
@@ -0,0 +1 @@
+fix-old-dep.patch
diff --git a/tests/configs/diesel-derives-2/debian/debcargo.toml b/tests/configs/diesel-derives-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/diesel-derives-2/debian/rules b/tests/configs/diesel-derives-2/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/dwrote-0.11/debian/debcargo.toml b/tests/configs/dwrote-0.11/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/dwrote-0.11/debian/rules b/tests/configs/dwrote-0.11/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/exa-0.10/debian/debcargo.toml b/tests/configs/exa-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/exa-0.10/debian/rules b/tests/configs/exa-0.10/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/exa/debian/debcargo.toml b/tests/configs/exa/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/exa/debian/rules b/tests/configs/exa/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/fd-find-8/debian/debcargo.toml b/tests/configs/fd-find-8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/fd-find-8/debian/rules b/tests/configs/fd-find-8/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/fsevent-0.4/debian/debcargo.toml b/tests/configs/fsevent-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/fsevent-0.4/debian/rules b/tests/configs/fsevent-0.4/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/fsevent-sys-2/debian/debcargo.toml b/tests/configs/fsevent-sys-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/fsevent-sys-2/debian/rules b/tests/configs/fsevent-sys-2/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/heapsize-plugin-0.1/debian/debcargo.toml b/tests/configs/heapsize-plugin-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/heapsize-plugin-0.1/debian/rules b/tests/configs/heapsize-plugin-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/http-types-2/debian/debcargo.toml b/tests/configs/http-types-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/http-types-2/debian/patches/fix-features.patch b/tests/configs/http-types-2/debian/patches/fix-features.patch
new file mode 100644 (file)
index 0000000..c357f23
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -83,7 +83,7 @@
+ version = "0.2.0"
+ [features]
+-async_std = ["fs"]
++async_std = ["async-std"] # replaces fs with deps of fs
+ cookie-secure = ["cookies", "cookie/secure"]
+ cookies = ["cookie"]
+ default = ["fs", "cookie-secure"]
diff --git a/tests/configs/http-types-2/debian/patches/series b/tests/configs/http-types-2/debian/patches/series
new file mode 100644 (file)
index 0000000..2447948
--- /dev/null
@@ -0,0 +1 @@
+fix-features.patch
diff --git a/tests/configs/hyperx-1/debian/debcargo.toml b/tests/configs/hyperx-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/hyperx-1/debian/patches/relax-percent-encoding.patch b/tests/configs/hyperx-1/debian/patches/relax-percent-encoding.patch
new file mode 100644 (file)
index 0000000..1868251
--- /dev/null
@@ -0,0 +1,13 @@
+Index: hyperx-1.4.0/Cargo.toml
+===================================================================
+--- hyperx-1.4.0.orig/Cargo.toml
++++ hyperx-1.4.0/Cargo.toml
+@@ -43,7 +43,7 @@ version = ">=0.3.1, <0.4"
+ version = ">=0.3.2, <0.4"
+ [dependencies.percent-encoding]
+-version = ">=2.1.0, <2.2"
++version = "2.1.0"
+ [dependencies.unicase]
+ version = ">=2.6.0, <2.7"
diff --git a/tests/configs/hyperx-1/debian/patches/series b/tests/configs/hyperx-1/debian/patches/series
new file mode 100644 (file)
index 0000000..0490e99
--- /dev/null
@@ -0,0 +1 @@
+relax-percent-encoding.patch
diff --git a/tests/configs/hyperx/debian/debcargo.toml b/tests/configs/hyperx/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/hyperx/debian/patches/relax-percent-encoding.patch b/tests/configs/hyperx/debian/patches/relax-percent-encoding.patch
new file mode 100644 (file)
index 0000000..1868251
--- /dev/null
@@ -0,0 +1,13 @@
+Index: hyperx-1.4.0/Cargo.toml
+===================================================================
+--- hyperx-1.4.0.orig/Cargo.toml
++++ hyperx-1.4.0/Cargo.toml
+@@ -43,7 +43,7 @@ version = ">=0.3.1, <0.4"
+ version = ">=0.3.2, <0.4"
+ [dependencies.percent-encoding]
+-version = ">=2.1.0, <2.2"
++version = "2.1.0"
+ [dependencies.unicase]
+ version = ">=2.6.0, <2.7"
diff --git a/tests/configs/hyperx/debian/patches/series b/tests/configs/hyperx/debian/patches/series
new file mode 100644 (file)
index 0000000..0490e99
--- /dev/null
@@ -0,0 +1 @@
+relax-percent-encoding.patch
diff --git a/tests/configs/iana-time-zone-0.1/debian/debcargo.toml b/tests/configs/iana-time-zone-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/iana-time-zone-0.1/debian/patches/fix-windows-dep.patch b/tests/configs/iana-time-zone-0.1/debian/patches/fix-windows-dep.patch
new file mode 100644 (file)
index 0000000..4cca3bb
--- /dev/null
@@ -0,0 +1,10 @@
+Index: iana-time-zone-0.1.60/Cargo.toml
+===================================================================
+--- iana-time-zone-0.1.60.orig/Cargo.toml
++++ iana-time-zone-0.1.60/Cargo.toml
+@@ -54,4 +54,4 @@ version = "0.1.5"
+ version = "0.1.1"
+ [target."cfg(target_os = \"windows\")".dependencies.windows-core]
+-version = ">=0.50, <=0.52"
++version = "0.52"
diff --git a/tests/configs/iana-time-zone-0.1/debian/patches/series b/tests/configs/iana-time-zone-0.1/debian/patches/series
new file mode 100644 (file)
index 0000000..1934007
--- /dev/null
@@ -0,0 +1 @@
+fix-windows-dep.patch
diff --git a/tests/configs/jetscii-0.3/debian/debcargo.toml b/tests/configs/jetscii-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/jetscii-0.3/debian/rules b/tests/configs/jetscii-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/kqueue-1/debian/debcargo.toml b/tests/configs/kqueue-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/kqueue-1/debian/rules b/tests/configs/kqueue-1/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/kqueue-sys-1/debian/debcargo.toml b/tests/configs/kqueue-sys-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/kqueue-sys-1/debian/rules b/tests/configs/kqueue-sys-1/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/libdav1d-sys-0.6/debian/debcargo.toml b/tests/configs/libdav1d-sys-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..1f2035a
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libdav1d-dev", "meson", "nasm"]
diff --git a/tests/configs/libdbus-sys-0.2/debian/debcargo.toml b/tests/configs/libdbus-sys-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..13f0492
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["libdbus-1-dev"]
diff --git a/tests/configs/mysqlclient-src-0.1/debian/debcargo.toml b/tests/configs/mysqlclient-src-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..90c331e
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libncurses-dev"]
diff --git a/tests/configs/mysqlclient-sys-0.2/debian/debcargo.toml b/tests/configs/mysqlclient-sys-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..16cf81b
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libmysqlclient-dev"]
diff --git a/tests/configs/mysqlclient-sys-0.4/debian/debcargo.toml b/tests/configs/mysqlclient-sys-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..16cf81b
--- /dev/null
@@ -0,0 +1,5 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+depends = ["libmysqlclient-dev"]
diff --git a/tests/configs/nasm-rs-0.2/debian/debcargo.toml b/tests/configs/nasm-rs-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..2c3ba3d
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["nasm"]
diff --git a/tests/configs/netlib-src-0.8/debian/debcargo.toml b/tests/configs/netlib-src-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..690060d
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["gfortran"]
diff --git a/tests/configs/nodrop-union-0.1/debian/debcargo.toml b/tests/configs/nodrop-union-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/nodrop-union-0.1/debian/rules b/tests/configs/nodrop-union-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/nom-4/debian/debcargo.toml b/tests/configs/nom-4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/nom-4/debian/rules b/tests/configs/nom-4/debian/rules
new file mode 100644 (file)
index 0000000..bbc019c
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate declares benches outside of crate path
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/old-version/debian/debcargo.toml b/tests/configs/old-version/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..544a9c6
--- /dev/null
@@ -0,0 +1,2 @@
+overlay = "."
+semver_suffix = true
diff --git a/tests/configs/once-cell-1/debian/debcargo.toml b/tests/configs/once-cell-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/onig-6/debian/debcargo.toml b/tests/configs/onig-6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/onig-6/debian/rules b/tests/configs/onig-6/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/onig-sys-69/debian/debcargo.toml b/tests/configs/onig-sys-69/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/onig-sys-69/debian/rules b/tests/configs/onig-sys-69/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/only-macos/debian/debcargo.toml b/tests/configs/only-macos/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/only-macos/debian/rules b/tests/configs/only-macos/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/only-windows/debian/debcargo.toml b/tests/configs/only-windows/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/only-windows/debian/rules b/tests/configs/only-windows/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/openssl-sys-0.9/debian/debcargo.toml b/tests/configs/openssl-sys-0.9/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..c8a4273
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["libssl-dev"]
diff --git a/tests/configs/openssl-sys-0.9/debian/patches/disable-bssl.patch b/tests/configs/openssl-sys-0.9/debian/patches/disable-bssl.patch
new file mode 100644 (file)
index 0000000..32e9b70
--- /dev/null
@@ -0,0 +1,14 @@
+Description: bssl-sys is a placeholder crate that doesn't actually compile as published on crates.io
+
+Index: openssl-sys-0.9.93/Cargo.toml
+===================================================================
+--- openssl-sys-0.9.93.orig/Cargo.toml
++++ openssl-sys-0.9.93/Cargo.toml
+@@ -34,4 +34,0 @@ repository = "https://github.com/sfackle
+-[dependencies.bssl-sys]
+-version = "0.1.0"
+-optional = true
+-
+@@ -61,1 +57,1 @@ version = "0.3.9"
+-unstable_boringssl = ["bssl-sys"]
++unstable_boringssl = []
diff --git a/tests/configs/openssl-sys-0.9/debian/patches/series b/tests/configs/openssl-sys-0.9/debian/patches/series
new file mode 100644 (file)
index 0000000..a8b638b
--- /dev/null
@@ -0,0 +1 @@
+disable-bssl.patch
diff --git a/tests/configs/packed-simd-0.3/debian/debcargo.toml b/tests/configs/packed-simd-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/packed-simd-0.3/debian/rules b/tests/configs/packed-simd-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/packed-simd-2-0.3/debian/debcargo.toml b/tests/configs/packed-simd-2-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/packed-simd-2-0.3/debian/rules b/tests/configs/packed-simd-2-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/petgraph-0.4/debian/debcargo.toml b/tests/configs/petgraph-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/petgraph-0.4/debian/patches/fix-old-dep.patch b/tests/configs/petgraph-0.4/debian/patches/fix-old-dep.patch
new file mode 100644 (file)
index 0000000..5ae18e6
--- /dev/null
@@ -0,0 +1,40 @@
+Crate authors like to put dev-dependencies in dependencies due to
+https://github.com/rust-lang/cargo/issues/1596
+
+Then due to lack of maintenance this pollutes the dependency set with old
+crates that no longer compile.
+
+Here, quickcheck 0.4 eventually depends on simd which no longer compiles.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -21,7 +21,7 @@
+ license = "MIT/Apache-2.0"
+ repository = "https://github.com/bluss/petgraph"
+ [package.metadata.docs.rs]
+-features = ["serde-1", "quickcheck"]
++features = ["serde-1"]
+ [package.metadata.release]
+ no-dev-version = true
+@@ -40,11 +40,6 @@
+ version = "0.3.0"
+ optional = true
+-[dependencies.quickcheck]
+-version = "0.4"
+-optional = true
+-default-features = false
+-
+ [dependencies.serde]
+ version = "1.0"
+ optional = true
+@@ -66,7 +61,7 @@
+ version = "0.3"
+ [features]
+-all = ["unstable", "quickcheck", "stable_graph", "graphmap"]
++all = ["unstable", "stable_graph", "graphmap"]
+ default = ["graphmap", "stable_graph"]
+ generate = []
+ graphmap = ["ordermap"]
diff --git a/tests/configs/petgraph-0.4/debian/patches/series b/tests/configs/petgraph-0.4/debian/patches/series
new file mode 100644 (file)
index 0000000..f385166
--- /dev/null
@@ -0,0 +1 @@
+fix-old-dep.patch
diff --git a/tests/configs/phf-generator-0.10/debian/debcargo.toml b/tests/configs/phf-generator-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..7591b7f
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+bin = false
diff --git a/tests/configs/pkg-config-0.3/debian/debcargo.toml b/tests/configs/pkg-config-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..7a9da8f
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["pkg-config"]
diff --git a/tests/configs/rav1e-0.6/debian/debcargo.toml b/tests/configs/rav1e-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..c644066
--- /dev/null
@@ -0,0 +1,8 @@
+semver_suffix = true
+overlay = "."
+
+[source]
+build_depends = [
+    "cargo-c:native",
+]
+
diff --git a/tests/configs/rav1e-0.6/debian/patches/relax-clap.diff b/tests/configs/rav1e-0.6/debian/patches/relax-clap.diff
new file mode 100644 (file)
index 0000000..18d19a9
--- /dev/null
@@ -0,0 +1,13 @@
+Index: rav1e-0.6.6/Cargo.toml
+===================================================================
+--- rav1e-0.6.6.orig/Cargo.toml
++++ rav1e-0.6.6/Cargo.toml
+@@ -111,7 +111,7 @@ optional = true
+ version = "1.0"
+ [dependencies.clap]
+-version = "=4.0.32"
++version = "4.0.32"
+ features = [
+     "color",
+     "std",
diff --git a/tests/configs/rav1e-0.6/debian/patches/series b/tests/configs/rav1e-0.6/debian/patches/series
new file mode 100644 (file)
index 0000000..7c3dcab
--- /dev/null
@@ -0,0 +1 @@
+relax-clap.diff
diff --git a/tests/configs/redis-0.17/debian/debcargo.toml b/tests/configs/redis-0.17/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/redis-0.17/debian/rules b/tests/configs/redis-0.17/debian/rules
new file mode 100644 (file)
index 0000000..304a2b4
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate is buggy; fails to declare "alloc" feature on futures-util
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/redox-syscall-0.1/debian/debcargo.toml b/tests/configs/redox-syscall-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/redox-syscall-0.1/debian/rules b/tests/configs/redox-syscall-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/redox-users-0.3/debian/debcargo.toml b/tests/configs/redox-users-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/redox-users-0.3/debian/rules b/tests/configs/redox-users-0.3/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/rhai-1/debian/debcargo.toml b/tests/configs/rhai-1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/rhai-1/debian/rules b/tests/configs/rhai-1/debian/rules
new file mode 100644 (file)
index 0000000..be9afde
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_dwz:
+       # Don't do anything. fails because of the
+       # https://github.com/rust-lang/rust/issues/66118
diff --git a/tests/configs/ring-0.13/debian/debcargo.toml b/tests/configs/ring-0.13/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/ring-0.13/debian/rules b/tests/configs/ring-0.13/debian/rules
new file mode 100644 (file)
index 0000000..f5e1085
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate is super-over-zealous with lint settings
+# overrides our cargo wrapper's --cap-lints warn
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/ring-0.14/debian/debcargo.toml b/tests/configs/ring-0.14/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/ring-0.14/debian/rules b/tests/configs/ring-0.14/debian/rules
new file mode 100644 (file)
index 0000000..f5e1085
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate is super-over-zealous with lint settings
+# overrides our cargo wrapper's --cap-lints warn
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/rust-hawktracer-sys-0.4/debian/debcargo.toml b/tests/configs/rust-hawktracer-sys-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/rust-hawktracer-sys-0.4/debian/rules b/tests/configs/rust-hawktracer-sys-0.4/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/rust-lzma-0.5/debian/debcargo.toml b/tests/configs/rust-lzma-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..4b97b62
--- /dev/null
@@ -0,0 +1,5 @@
+overlay ="."
+semver_suffix = true
+
+[packages.lib]
+depends = ["liblzma-dev"]
diff --git a/tests/configs/salvo-extra-0.16/debian/debcargo.toml b/tests/configs/salvo-extra-0.16/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/salvo-extra-0.16/debian/rules b/tests/configs/salvo-extra-0.16/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/security-framework-2/debian/debcargo.toml b/tests/configs/security-framework-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/security-framework-2/debian/rules b/tests/configs/security-framework-2/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/security-framework-sys-2/debian/debcargo.toml b/tests/configs/security-framework-sys-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/security-framework-sys-2/debian/rules b/tests/configs/security-framework-sys-2/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/serde-qs-0.8/debian/debcargo.toml b/tests/configs/serde-qs-0.8/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/serde-qs-0.8/debian/patches/fix-actix-web-dep.patch b/tests/configs/serde-qs-0.8/debian/patches/fix-actix-web-dep.patch
new file mode 100644 (file)
index 0000000..d44aff6
--- /dev/null
@@ -0,0 +1,30 @@
+actix-web eventually depends on actix-connect 1.0.2
+actix-connect 1.0.2 depends on prerelease trust-dns-resolver 0.18.0-alpha.2,
+which declares broken deps on trust-dns-proto "0.18.0" - should be "=0.18.0-alpha.2"
+
+debcargo doesn't support prerelease versions because semver compatibility
+doesn't apply. So patching trust-dns-resolver to fix their bug is not an
+option for us here. So just disable actix-web 2 here.
+
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -30,12 +30,6 @@
+ default-features = false
+ package = "actix-web"
+-[dependencies.actix-web2]
+-version = "2.0"
+-optional = true
+-default-features = false
+-package = "actix-web"
+-
+ [dependencies.futures]
+ version = "0.3"
+ optional = true
+@@ -75,6 +69,5 @@
+ [features]
+ actix = ["actix-web", "futures"]
+-actix2 = ["actix-web2", "futures"]
+ default = []
+ warp = ["futures", "tracing", "warp-framework"]
diff --git a/tests/configs/serde-qs-0.8/debian/patches/series b/tests/configs/serde-qs-0.8/debian/patches/series
new file mode 100644 (file)
index 0000000..03ed99c
--- /dev/null
@@ -0,0 +1 @@
+fix-actix-web-dep.patch
diff --git a/tests/configs/servo-fontconfig-sys-5/debian/debcargo.toml b/tests/configs/servo-fontconfig-sys-5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..83cc783
--- /dev/null
@@ -0,0 +1,4 @@
+semver_suffix = true
+
+[packages.lib]
+depends = ["libfontconfig-dev"]
diff --git a/tests/configs/sleef-sys-0.1/debian/debcargo.toml b/tests/configs/sleef-sys-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/sleef-sys-0.1/debian/rules b/tests/configs/sleef-sys-0.1/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/spin-0.4/debian/debcargo.toml b/tests/configs/spin-0.4/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/spin-0.4/debian/rules b/tests/configs/spin-0.4/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/structopt-0.3/debian/debcargo.toml b/tests/configs/structopt-0.3/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/structopt-0.3/debian/patches/disable-lint-feature.diff b/tests/configs/structopt-0.3/debian/patches/disable-lint-feature.diff
new file mode 100644 (file)
index 0000000..5bdae4f
--- /dev/null
@@ -0,0 +1,13 @@
+Index: structopt/Cargo.toml
+===================================================================
+--- structopt.orig/Cargo.toml
++++ structopt/Cargo.toml
+@@ -51,7 +51,7 @@ color = ["clap/color"]
+ debug = ["clap/debug"]
+ default = ["clap/default"]
+ doc = ["clap/doc"]
+-lints = ["clap/lints"]
++#lints = ["clap/lints"]
+ no_cargo = ["clap/no_cargo"]
+ #paw = ["structopt-derive/paw", "paw_dep"]
+ suggestions = ["clap/suggestions"]
diff --git a/tests/configs/structopt-0.3/debian/patches/disable-paw.diff b/tests/configs/structopt-0.3/debian/patches/disable-paw.diff
new file mode 100644 (file)
index 0000000..c1ba307
--- /dev/null
@@ -0,0 +1,28 @@
+Index: structopt/Cargo.toml
+===================================================================
+--- structopt.orig/Cargo.toml
++++ structopt/Cargo.toml
+@@ -28,10 +28,10 @@
+ [dependencies.lazy_static]
+ version = "1.4.0"
+-[dependencies.paw_dep]
+-version = "1"
+-optional = true
+-package = "paw"
++#[dependencies.paw_dep]
++#version = "1"
++#optional = true
++#package = "paw"
+ [dependencies.structopt-derive]
+ version = "=0.4.18"
+@@ -53,7 +53,7 @@
+ doc = ["clap/doc"]
+ lints = ["clap/lints"]
+ no_cargo = ["clap/no_cargo"]
+-paw = ["structopt-derive/paw", "paw_dep"]
++#paw = ["structopt-derive/paw", "paw_dep"]
+ suggestions = ["clap/suggestions"]
+ wrap_help = ["clap/wrap_help"]
+ yaml = ["clap/yaml"]
diff --git a/tests/configs/structopt-0.3/debian/patches/series b/tests/configs/structopt-0.3/debian/patches/series
new file mode 100644 (file)
index 0000000..d5e4f35
--- /dev/null
@@ -0,0 +1,2 @@
+disable-paw.diff
+disable-lint-feature.diff
diff --git a/tests/configs/system-configuration-0.5/debian/debcargo.toml b/tests/configs/system-configuration-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-0.5/debian/rules b/tests/configs/system-configuration-0.5/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-configuration-0.6/debian/debcargo.toml b/tests/configs/system-configuration-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-0.6/debian/rules b/tests/configs/system-configuration-0.6/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-configuration-sys-0.5/debian/debcargo.toml b/tests/configs/system-configuration-sys-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-sys-0.5/debian/rules b/tests/configs/system-configuration-sys-0.5/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-configuration-sys-0.6/debian/debcargo.toml b/tests/configs/system-configuration-sys-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-configuration-sys-0.6/debian/rules b/tests/configs/system-configuration-sys-0.6/debian/rules
new file mode 100644 (file)
index 0000000..e3dbf82
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on macos
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-apple-darwin) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/system-deps-6/debian/debcargo.toml b/tests/configs/system-deps-6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/system-deps-6/debian/rules b/tests/configs/system-deps-6/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/tiny-keccak-2/debian/debcargo.toml b/tests/configs/tiny-keccak-2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/tiny-keccak-2/debian/rules b/tests/configs/tiny-keccak-2/debian/rules
new file mode 100644 (file)
index 0000000..bf5ebf1
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# crate errors on purpose when no features are enabled
+override_dh_auto_test:
+       dh_auto_test || true
diff --git a/tests/configs/vcpkg-0.2/debian/debcargo.toml b/tests/configs/vcpkg-0.2/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..0c74ebf
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+excludes = ["test-data/**"]
diff --git a/tests/configs/wepoll-ffi-0.1/debian/debcargo.toml b/tests/configs/wepoll-ffi-0.1/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/wepoll-ffi-0.1/debian/rules b/tests/configs/wepoll-ffi-0.1/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.32/debian/debcargo.toml b/tests/configs/windows-0.32/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-0.32/debian/rules b/tests/configs/windows-0.32/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.48/debian/debcargo.toml b/tests/configs/windows-0.48/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-0.48/debian/rules b/tests/configs/windows-0.48/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.54/debian/changelog b/tests/configs/windows-0.54/debian/changelog
new file mode 100644 (file)
index 0000000..44e099c
--- /dev/null
@@ -0,0 +1,6 @@
+rust-windows-0.54 (0.54.0-1) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package windows 0.54.0 from crates.io using debcargo 2.6.1
+
+ -- Fabian Grünbichler <debian@fabian.gruenbichler.email>  Sat, 6 Jul 2024 21:13:52 +0200
diff --git a/tests/configs/windows-0.54/debian/debcargo.toml b/tests/configs/windows-0.54/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..96a9bd9
--- /dev/null
@@ -0,0 +1,7 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+test_is_broken = false
+[packages."lib+Win32_Foundation"]
+test_is_broken = false
diff --git a/tests/configs/windows-0.54/debian/patches/remove-cycles.patch b/tests/configs/windows-0.54/debian/patches/remove-cycles.patch
new file mode 100644 (file)
index 0000000..1719bff
--- /dev/null
@@ -0,0 +1,1382 @@
+Index: rust-windows-0.54-0.54.0/Cargo.toml
+===================================================================
+--- rust-windows-0.54-0.54.0.orig/Cargo.toml
++++ rust-windows-0.54-0.54.0/Cargo.toml
+@@ -46,692 +46,692 @@ optional = true
+ version = "0.52.3"
+ [features]
+-AI = ["Foundation"]
+-AI_MachineLearning = ["AI"]
+-ApplicationModel = ["Foundation"]
+-ApplicationModel_Activation = ["ApplicationModel"]
+-ApplicationModel_AppExtensions = ["ApplicationModel"]
+-ApplicationModel_AppService = ["ApplicationModel"]
+-ApplicationModel_Appointments = ["ApplicationModel"]
+-ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Background = ["ApplicationModel"]
+-ApplicationModel_Calls = ["ApplicationModel"]
+-ApplicationModel_Calls_Background = ["ApplicationModel_Calls"]
+-ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"]
+-ApplicationModel_Chat = ["ApplicationModel"]
+-ApplicationModel_CommunicationBlocking = ["ApplicationModel"]
+-ApplicationModel_Contacts = ["ApplicationModel"]
+-ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"]
+-ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"]
+-ApplicationModel_ConversationalAgent = ["ApplicationModel"]
+-ApplicationModel_Core = ["ApplicationModel"]
+-ApplicationModel_DataTransfer = ["ApplicationModel"]
+-ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"]
+-ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_Email = ["ApplicationModel"]
+-ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"]
+-ApplicationModel_ExtendedExecution = ["ApplicationModel"]
+-ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"]
+-ApplicationModel_Holographic = ["ApplicationModel"]
+-ApplicationModel_LockScreen = ["ApplicationModel"]
+-ApplicationModel_Payments = ["ApplicationModel"]
+-ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"]
+-ApplicationModel_Preview = ["ApplicationModel"]
+-ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"]
+-ApplicationModel_Resources = ["ApplicationModel"]
+-ApplicationModel_Resources_Core = ["ApplicationModel_Resources"]
+-ApplicationModel_Resources_Management = ["ApplicationModel_Resources"]
+-ApplicationModel_Search = ["ApplicationModel"]
+-ApplicationModel_Search_Core = ["ApplicationModel_Search"]
+-ApplicationModel_Store = ["ApplicationModel"]
+-ApplicationModel_Store_LicenseManagement = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview_InstallControl = ["ApplicationModel_Store_Preview"]
+-ApplicationModel_UserActivities = ["ApplicationModel"]
+-ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"]
+-ApplicationModel_UserDataAccounts = ["ApplicationModel"]
+-ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataTasks = ["ApplicationModel"]
+-ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"]
+-ApplicationModel_VoiceCommands = ["ApplicationModel"]
+-ApplicationModel_Wallet = ["ApplicationModel"]
+-ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"]
+-Data = ["Foundation"]
+-Data_Html = ["Data"]
+-Data_Json = ["Data"]
+-Data_Pdf = ["Data"]
+-Data_Text = ["Data"]
+-Data_Xml = ["Data"]
+-Data_Xml_Dom = ["Data_Xml"]
+-Data_Xml_Xsl = ["Data_Xml"]
+-Devices = ["Foundation"]
+-Devices_Adc = ["Devices"]
+-Devices_Adc_Provider = ["Devices_Adc"]
+-Devices_Background = ["Devices"]
+-Devices_Bluetooth = ["Devices"]
+-Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Background = ["Devices_Bluetooth"]
+-Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"]
+-Devices_Custom = ["Devices"]
+-Devices_Display = ["Devices"]
+-Devices_Display_Core = ["Devices_Display"]
+-Devices_Enumeration = ["Devices"]
+-Devices_Enumeration_Pnp = ["Devices_Enumeration"]
+-Devices_Geolocation = ["Devices"]
+-Devices_Geolocation_Geofencing = ["Devices_Geolocation"]
+-Devices_Geolocation_Provider = ["Devices_Geolocation"]
+-Devices_Gpio = ["Devices"]
+-Devices_Gpio_Provider = ["Devices_Gpio"]
+-Devices_Haptics = ["Devices"]
+-Devices_HumanInterfaceDevice = ["Devices"]
+-Devices_I2c = ["Devices"]
+-Devices_I2c_Provider = ["Devices_I2c"]
+-Devices_Input = ["Devices"]
+-Devices_Input_Preview = ["Devices_Input"]
+-Devices_Lights = ["Devices"]
+-Devices_Lights_Effects = ["Devices_Lights"]
+-Devices_Midi = ["Devices"]
+-Devices_PointOfService = ["Devices"]
+-Devices_PointOfService_Provider = ["Devices_PointOfService"]
+-Devices_Portable = ["Devices"]
+-Devices_Power = ["Devices"]
+-Devices_Printers = ["Devices"]
+-Devices_Printers_Extensions = ["Devices_Printers"]
+-Devices_Pwm = ["Devices"]
+-Devices_Pwm_Provider = ["Devices_Pwm"]
+-Devices_Radios = ["Devices"]
+-Devices_Scanners = ["Devices"]
+-Devices_Sensors = ["Devices"]
+-Devices_Sensors_Custom = ["Devices_Sensors"]
+-Devices_SerialCommunication = ["Devices"]
+-Devices_SmartCards = ["Devices"]
+-Devices_Sms = ["Devices"]
+-Devices_Spi = ["Devices"]
+-Devices_Spi_Provider = ["Devices_Spi"]
+-Devices_Usb = ["Devices"]
+-Devices_WiFi = ["Devices"]
+-Devices_WiFiDirect = ["Devices"]
+-Devices_WiFiDirect_Services = ["Devices_WiFiDirect"]
+-Embedded = ["Foundation"]
+-Embedded_DeviceLockdown = ["Embedded"]
++AI = []
++AI_MachineLearning = []
++ApplicationModel = []
++ApplicationModel_Activation = []
++ApplicationModel_AppExtensions = []
++ApplicationModel_AppService = []
++ApplicationModel_Appointments = []
++ApplicationModel_Appointments_AppointmentsProvider = []
++ApplicationModel_Appointments_DataProvider = []
++ApplicationModel_Background = []
++ApplicationModel_Calls = []
++ApplicationModel_Calls_Background = []
++ApplicationModel_Calls_Provider = []
++ApplicationModel_Chat = []
++ApplicationModel_CommunicationBlocking = []
++ApplicationModel_Contacts = []
++ApplicationModel_Contacts_DataProvider = []
++ApplicationModel_Contacts_Provider = []
++ApplicationModel_ConversationalAgent = []
++ApplicationModel_Core = []
++ApplicationModel_DataTransfer = []
++ApplicationModel_DataTransfer_DragDrop = []
++ApplicationModel_DataTransfer_DragDrop_Core = []
++ApplicationModel_DataTransfer_ShareTarget = []
++ApplicationModel_Email = []
++ApplicationModel_Email_DataProvider = []
++ApplicationModel_ExtendedExecution = []
++ApplicationModel_ExtendedExecution_Foreground = []
++ApplicationModel_Holographic = []
++ApplicationModel_LockScreen = []
++ApplicationModel_Payments = []
++ApplicationModel_Payments_Provider = []
++ApplicationModel_Preview = []
++ApplicationModel_Preview_Holographic = []
++ApplicationModel_Preview_InkWorkspace = []
++ApplicationModel_Preview_Notes = []
++ApplicationModel_Resources = []
++ApplicationModel_Resources_Core = []
++ApplicationModel_Resources_Management = []
++ApplicationModel_Search = []
++ApplicationModel_Search_Core = []
++ApplicationModel_Store = []
++ApplicationModel_Store_LicenseManagement = []
++ApplicationModel_Store_Preview = []
++ApplicationModel_Store_Preview_InstallControl = []
++ApplicationModel_UserActivities = []
++ApplicationModel_UserActivities_Core = []
++ApplicationModel_UserDataAccounts = []
++ApplicationModel_UserDataAccounts_Provider = []
++ApplicationModel_UserDataAccounts_SystemAccess = []
++ApplicationModel_UserDataTasks = []
++ApplicationModel_UserDataTasks_DataProvider = []
++ApplicationModel_VoiceCommands = []
++ApplicationModel_Wallet = []
++ApplicationModel_Wallet_System = []
++Data = []
++Data_Html = []
++Data_Json = []
++Data_Pdf = []
++Data_Text = []
++Data_Xml = []
++Data_Xml_Dom = []
++Data_Xml_Xsl = []
++Devices = []
++Devices_Adc = []
++Devices_Adc_Provider = []
++Devices_Background = []
++Devices_Bluetooth = []
++Devices_Bluetooth_Advertisement = []
++Devices_Bluetooth_Background = []
++Devices_Bluetooth_GenericAttributeProfile = []
++Devices_Bluetooth_Rfcomm = []
++Devices_Custom = []
++Devices_Display = []
++Devices_Display_Core = []
++Devices_Enumeration = []
++Devices_Enumeration_Pnp = []
++Devices_Geolocation = []
++Devices_Geolocation_Geofencing = []
++Devices_Geolocation_Provider = []
++Devices_Gpio = []
++Devices_Gpio_Provider = []
++Devices_Haptics = []
++Devices_HumanInterfaceDevice = []
++Devices_I2c = []
++Devices_I2c_Provider = []
++Devices_Input = []
++Devices_Input_Preview = []
++Devices_Lights = []
++Devices_Lights_Effects = []
++Devices_Midi = []
++Devices_PointOfService = []
++Devices_PointOfService_Provider = []
++Devices_Portable = []
++Devices_Power = []
++Devices_Printers = []
++Devices_Printers_Extensions = []
++Devices_Pwm = []
++Devices_Pwm_Provider = []
++Devices_Radios = []
++Devices_Scanners = []
++Devices_Sensors = []
++Devices_Sensors_Custom = []
++Devices_SerialCommunication = []
++Devices_SmartCards = []
++Devices_Sms = []
++Devices_Spi = []
++Devices_Spi_Provider = []
++Devices_Usb = []
++Devices_WiFi = []
++Devices_WiFiDirect = []
++Devices_WiFiDirect_Services = []
++Embedded = []
++Embedded_DeviceLockdown = []
+ Foundation = []
+-Foundation_Collections = ["Foundation"]
+-Foundation_Diagnostics = ["Foundation"]
+-Foundation_Metadata = ["Foundation"]
+-Foundation_Numerics = ["Foundation"]
+-Gaming = ["Foundation"]
+-Gaming_Input = ["Gaming"]
+-Gaming_Input_Custom = ["Gaming_Input"]
+-Gaming_Input_ForceFeedback = ["Gaming_Input"]
+-Gaming_Input_Preview = ["Gaming_Input"]
+-Gaming_Preview = ["Gaming"]
+-Gaming_Preview_GamesEnumeration = ["Gaming_Preview"]
+-Gaming_UI = ["Gaming"]
+-Gaming_XboxLive = ["Gaming"]
+-Gaming_XboxLive_Storage = ["Gaming_XboxLive"]
+-Globalization = ["Foundation"]
+-Globalization_Collation = ["Globalization"]
+-Globalization_DateTimeFormatting = ["Globalization"]
+-Globalization_Fonts = ["Globalization"]
+-Globalization_NumberFormatting = ["Globalization"]
+-Globalization_PhoneNumberFormatting = ["Globalization"]
+-Graphics = ["Foundation"]
+-Graphics_Capture = ["Graphics"]
+-Graphics_DirectX = ["Graphics"]
+-Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"]
+-Graphics_Display = ["Graphics"]
+-Graphics_Display_Core = ["Graphics_Display"]
+-Graphics_Effects = ["Graphics"]
+-Graphics_Holographic = ["Graphics"]
+-Graphics_Imaging = ["Graphics"]
+-Graphics_Printing = ["Graphics"]
+-Graphics_Printing3D = ["Graphics"]
+-Graphics_Printing_OptionDetails = ["Graphics_Printing"]
+-Graphics_Printing_PrintSupport = ["Graphics_Printing"]
+-Graphics_Printing_PrintTicket = ["Graphics_Printing"]
+-Graphics_Printing_Workflow = ["Graphics_Printing"]
+-Management = ["Foundation"]
+-Management_Core = ["Management"]
+-Management_Deployment = ["Management"]
+-Management_Deployment_Preview = ["Management_Deployment"]
+-Management_Policies = ["Management"]
+-Management_Update = ["Management"]
+-Management_Workplace = ["Management"]
+-Media = ["Foundation"]
+-Media_AppBroadcasting = ["Media"]
+-Media_AppRecording = ["Media"]
+-Media_Audio = ["Media"]
+-Media_Capture = ["Media"]
+-Media_Capture_Core = ["Media_Capture"]
+-Media_Capture_Frames = ["Media_Capture"]
+-Media_Casting = ["Media"]
+-Media_ClosedCaptioning = ["Media"]
+-Media_ContentRestrictions = ["Media"]
+-Media_Control = ["Media"]
+-Media_Core = ["Media"]
+-Media_Core_Preview = ["Media_Core"]
+-Media_Devices = ["Media"]
+-Media_Devices_Core = ["Media_Devices"]
+-Media_DialProtocol = ["Media"]
+-Media_Editing = ["Media"]
+-Media_Effects = ["Media"]
+-Media_FaceAnalysis = ["Media"]
+-Media_Import = ["Media"]
+-Media_MediaProperties = ["Media"]
+-Media_Miracast = ["Media"]
+-Media_Ocr = ["Media"]
+-Media_PlayTo = ["Media"]
+-Media_Playback = ["Media"]
+-Media_Playlists = ["Media"]
+-Media_Protection = ["Media"]
+-Media_Protection_PlayReady = ["Media_Protection"]
+-Media_Render = ["Media"]
+-Media_SpeechRecognition = ["Media"]
+-Media_SpeechSynthesis = ["Media"]
+-Media_Streaming = ["Media"]
+-Media_Streaming_Adaptive = ["Media_Streaming"]
+-Media_Transcoding = ["Media"]
+-Networking = ["Foundation"]
+-Networking_BackgroundTransfer = ["Networking"]
+-Networking_Connectivity = ["Networking"]
+-Networking_NetworkOperators = ["Networking"]
+-Networking_Proximity = ["Networking"]
+-Networking_PushNotifications = ["Networking"]
+-Networking_ServiceDiscovery = ["Networking"]
+-Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"]
+-Networking_Sockets = ["Networking"]
+-Networking_Vpn = ["Networking"]
+-Networking_XboxLive = ["Networking"]
+-Perception = ["Foundation"]
+-Perception_Automation = ["Perception"]
+-Perception_Automation_Core = ["Perception_Automation"]
+-Perception_People = ["Perception"]
+-Perception_Spatial = ["Perception"]
+-Perception_Spatial_Preview = ["Perception_Spatial"]
+-Perception_Spatial_Surfaces = ["Perception_Spatial"]
+-Phone = ["Foundation"]
+-Phone_ApplicationModel = ["Phone"]
+-Phone_Devices = ["Phone"]
+-Phone_Devices_Notification = ["Phone_Devices"]
+-Phone_Devices_Power = ["Phone_Devices"]
+-Phone_Management = ["Phone"]
+-Phone_Management_Deployment = ["Phone_Management"]
+-Phone_Media = ["Phone"]
+-Phone_Media_Devices = ["Phone_Media"]
+-Phone_Notification = ["Phone"]
+-Phone_Notification_Management = ["Phone_Notification"]
+-Phone_PersonalInformation = ["Phone"]
+-Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"]
+-Phone_Speech = ["Phone"]
+-Phone_Speech_Recognition = ["Phone_Speech"]
+-Phone_StartScreen = ["Phone"]
+-Phone_System = ["Phone"]
+-Phone_System_Power = ["Phone_System"]
+-Phone_System_Profile = ["Phone_System"]
+-Phone_System_UserProfile = ["Phone_System"]
+-Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"]
+-Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"]
+-Phone_UI = ["Phone"]
+-Phone_UI_Input = ["Phone_UI"]
+-Security = ["Foundation"]
+-Security_Authentication = ["Security"]
+-Security_Authentication_Identity = ["Security_Authentication"]
+-Security_Authentication_Identity_Core = ["Security_Authentication_Identity"]
+-Security_Authentication_OnlineId = ["Security_Authentication"]
+-Security_Authentication_Web = ["Security_Authentication"]
+-Security_Authentication_Web_Core = ["Security_Authentication_Web"]
+-Security_Authentication_Web_Provider = ["Security_Authentication_Web"]
+-Security_Authorization = ["Security"]
+-Security_Authorization_AppCapabilityAccess = ["Security_Authorization"]
+-Security_Credentials = ["Security"]
+-Security_Credentials_UI = ["Security_Credentials"]
+-Security_Cryptography = ["Security"]
+-Security_Cryptography_Certificates = ["Security_Cryptography"]
+-Security_Cryptography_Core = ["Security_Cryptography"]
+-Security_Cryptography_DataProtection = ["Security_Cryptography"]
+-Security_DataProtection = ["Security"]
+-Security_EnterpriseData = ["Security"]
+-Security_ExchangeActiveSyncProvisioning = ["Security"]
+-Security_Isolation = ["Security"]
+-Services = ["Foundation"]
+-Services_Maps = ["Services"]
+-Services_Maps_Guidance = ["Services_Maps"]
+-Services_Maps_LocalSearch = ["Services_Maps"]
+-Services_Maps_OfflineMaps = ["Services_Maps"]
+-Services_Store = ["Services"]
+-Services_TargetedContent = ["Services"]
+-Storage = ["Foundation"]
+-Storage_AccessCache = ["Storage"]
+-Storage_BulkAccess = ["Storage"]
+-Storage_Compression = ["Storage"]
+-Storage_FileProperties = ["Storage"]
+-Storage_Pickers = ["Storage"]
+-Storage_Pickers_Provider = ["Storage_Pickers"]
+-Storage_Provider = ["Storage"]
+-Storage_Search = ["Storage"]
+-Storage_Streams = ["Storage"]
+-System = ["Foundation"]
+-System_Diagnostics = ["System"]
+-System_Diagnostics_DevicePortal = ["System_Diagnostics"]
+-System_Diagnostics_Telemetry = ["System_Diagnostics"]
+-System_Diagnostics_TraceReporting = ["System_Diagnostics"]
+-System_Display = ["System"]
+-System_Implementation = ["System"]
+-System_Implementation_FileExplorer = ["System_Implementation"]
+-System_Inventory = ["System"]
+-System_Power = ["System"]
+-System_Profile = ["System"]
+-System_Profile_SystemManufacturers = ["System_Profile"]
+-System_RemoteDesktop = ["System"]
+-System_RemoteDesktop_Input = ["System_RemoteDesktop"]
+-System_RemoteDesktop_Provider = ["System_RemoteDesktop"]
+-System_RemoteSystems = ["System"]
+-System_Threading = ["System"]
+-System_Threading_Core = ["System_Threading"]
+-System_Update = ["System"]
+-System_UserProfile = ["System"]
+-UI = ["Foundation"]
+-UI_Accessibility = ["UI"]
+-UI_ApplicationSettings = ["UI"]
+-UI_Composition = ["UI"]
+-UI_Composition_Core = ["UI_Composition"]
+-UI_Composition_Desktop = ["UI_Composition"]
+-UI_Composition_Diagnostics = ["UI_Composition"]
+-UI_Composition_Effects = ["UI_Composition"]
+-UI_Composition_Interactions = ["UI_Composition"]
+-UI_Composition_Scenes = ["UI_Composition"]
+-UI_Core = ["UI"]
+-UI_Core_AnimationMetrics = ["UI_Core"]
+-UI_Core_Preview = ["UI_Core"]
+-UI_Input = ["UI"]
+-UI_Input_Core = ["UI_Input"]
+-UI_Input_Inking = ["UI_Input"]
+-UI_Input_Inking_Analysis = ["UI_Input_Inking"]
+-UI_Input_Inking_Core = ["UI_Input_Inking"]
+-UI_Input_Inking_Preview = ["UI_Input_Inking"]
+-UI_Input_Preview = ["UI_Input"]
+-UI_Input_Preview_Injection = ["UI_Input_Preview"]
+-UI_Input_Spatial = ["UI_Input"]
+-UI_Notifications = ["UI"]
+-UI_Notifications_Management = ["UI_Notifications"]
+-UI_Notifications_Preview = ["UI_Notifications"]
+-UI_Popups = ["UI"]
+-UI_Shell = ["UI"]
+-UI_StartScreen = ["UI"]
+-UI_Text = ["UI"]
+-UI_Text_Core = ["UI_Text"]
+-UI_UIAutomation = ["UI"]
+-UI_UIAutomation_Core = ["UI_UIAutomation"]
+-UI_ViewManagement = ["UI"]
+-UI_ViewManagement_Core = ["UI_ViewManagement"]
+-UI_WebUI = ["UI"]
+-UI_WebUI_Core = ["UI_WebUI"]
+-UI_WindowManagement = ["UI"]
+-UI_WindowManagement_Preview = ["UI_WindowManagement"]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Web = ["Foundation"]
+-Web_AtomPub = ["Web"]
+-Web_Http = ["Web"]
+-Web_Http_Diagnostics = ["Web_Http"]
+-Web_Http_Filters = ["Web_Http"]
+-Web_Http_Headers = ["Web_Http"]
+-Web_Syndication = ["Web"]
+-Web_UI = ["Web"]
+-Web_UI_Interop = ["Web_UI"]
+-Win32 = ["Win32_Foundation"]
+-Win32_AI = ["Win32"]
+-Win32_AI_MachineLearning = ["Win32_AI"]
+-Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"]
+-Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Data_Xml = ["Win32_Data"]
+-Win32_Data_Xml_MsXml = ["Win32_Data_Xml"]
+-Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAccess = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_FunctionDiscovery = ["Win32_Devices"]
+-Win32_Devices_Geolocation = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_ImageAcquisition = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"]
+-Win32_Graphics_DXCore = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"]
+-Win32_Graphics_Direct3D = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D10 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_DirectComposition = ["Win32_Graphics"]
+-Win32_Graphics_DirectDraw = ["Win32_Graphics"]
+-Win32_Graphics_DirectManipulation = ["Win32_Graphics"]
+-Win32_Graphics_DirectWrite = ["Win32_Graphics"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_Imaging = ["Win32_Graphics"]
+-Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_Audio_Apo = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"]
+-Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"]
+-Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"]
+-Win32_Media_DeviceManager = ["Win32_Media"]
+-Win32_Media_DirectShow = ["Win32_Media"]
+-Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"]
+-Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_LibrarySharingServices = ["Win32_Media"]
+-Win32_Media_MediaFoundation = ["Win32_Media"]
+-Win32_Media_MediaPlayer = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_PictureAcquisition = ["Win32_Media"]
+-Win32_Media_Speech = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_NetworkListManager = ["Win32_Networking"]
+-Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Authorization_UI = ["Win32_Security_Authorization"]
+-Win32_Security_ConfigurationSnapin = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_Tpm = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DataDeduplication = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_EnhancedStorage = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileServerResourceManager = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_VirtualDiskService = ["Win32_Storage"]
+-Win32_Storage_Vss = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_AssessmentTool = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_CallObj = ["Win32_System_Com"]
+-Win32_System_Com_ChannelCredentials = ["Win32_System_Com"]
+-Win32_System_Com_Events = ["Win32_System_Com"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_UI = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_Contacts = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DesktopSharing = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Mmc = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_ParentalControls = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_RealTimeCommunications = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteAssistance = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_ServerBackup = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SettingsManagementInfrastructure = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_SideShow = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_TaskScheduler = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_TransactionServer = ["Win32_System"]
+-Win32_System_UpdateAgent = ["Win32_System"]
+-Win32_System_UpdateAssessment = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WinRT = ["Win32_System"]
+-Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Composition = ["Win32_System_WinRT"]
+-Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Display = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Holographic = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Isolation = ["Win32_System_WinRT"]
+-Win32_System_WinRT_ML = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Media = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Metadata = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Pdf = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Printing = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Shell = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Storage = ["Win32_System_WinRT"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_WindowsSync = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_Animation = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_Ink = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Radial = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Notifications = ["Win32_UI"]
+-Win32_UI_Ribbon = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_UI_Wpf = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
++Foundation_Collections = []
++Foundation_Diagnostics = []
++Foundation_Metadata = []
++Foundation_Numerics = []
++Gaming = []
++Gaming_Input = []
++Gaming_Input_Custom = []
++Gaming_Input_ForceFeedback = []
++Gaming_Input_Preview = []
++Gaming_Preview = []
++Gaming_Preview_GamesEnumeration = []
++Gaming_UI = []
++Gaming_XboxLive = []
++Gaming_XboxLive_Storage = []
++Globalization = []
++Globalization_Collation = []
++Globalization_DateTimeFormatting = []
++Globalization_Fonts = []
++Globalization_NumberFormatting = []
++Globalization_PhoneNumberFormatting = []
++Graphics = []
++Graphics_Capture = []
++Graphics_DirectX = []
++Graphics_DirectX_Direct3D11 = []
++Graphics_Display = []
++Graphics_Display_Core = []
++Graphics_Effects = []
++Graphics_Holographic = []
++Graphics_Imaging = []
++Graphics_Printing = []
++Graphics_Printing3D = []
++Graphics_Printing_OptionDetails = []
++Graphics_Printing_PrintSupport = []
++Graphics_Printing_PrintTicket = []
++Graphics_Printing_Workflow = []
++Management = []
++Management_Core = []
++Management_Deployment = []
++Management_Deployment_Preview = []
++Management_Policies = []
++Management_Update = []
++Management_Workplace = []
++Media = []
++Media_AppBroadcasting = []
++Media_AppRecording = []
++Media_Audio = []
++Media_Capture = []
++Media_Capture_Core = []
++Media_Capture_Frames = []
++Media_Casting = []
++Media_ClosedCaptioning = []
++Media_ContentRestrictions = []
++Media_Control = []
++Media_Core = []
++Media_Core_Preview = []
++Media_Devices = []
++Media_Devices_Core = []
++Media_DialProtocol = []
++Media_Editing = []
++Media_Effects = []
++Media_FaceAnalysis = []
++Media_Import = []
++Media_MediaProperties = []
++Media_Miracast = []
++Media_Ocr = []
++Media_PlayTo = []
++Media_Playback = []
++Media_Playlists = []
++Media_Protection = []
++Media_Protection_PlayReady = []
++Media_Render = []
++Media_SpeechRecognition = []
++Media_SpeechSynthesis = []
++Media_Streaming = []
++Media_Streaming_Adaptive = []
++Media_Transcoding = []
++Networking = []
++Networking_BackgroundTransfer = []
++Networking_Connectivity = []
++Networking_NetworkOperators = []
++Networking_Proximity = []
++Networking_PushNotifications = []
++Networking_ServiceDiscovery = []
++Networking_ServiceDiscovery_Dnssd = []
++Networking_Sockets = []
++Networking_Vpn = []
++Networking_XboxLive = []
++Perception = []
++Perception_Automation = []
++Perception_Automation_Core = []
++Perception_People = []
++Perception_Spatial = []
++Perception_Spatial_Preview = []
++Perception_Spatial_Surfaces = []
++Phone = []
++Phone_ApplicationModel = []
++Phone_Devices = []
++Phone_Devices_Notification = []
++Phone_Devices_Power = []
++Phone_Management = []
++Phone_Management_Deployment = []
++Phone_Media = []
++Phone_Media_Devices = []
++Phone_Notification = []
++Phone_Notification_Management = []
++Phone_PersonalInformation = []
++Phone_PersonalInformation_Provisioning = []
++Phone_Speech = []
++Phone_Speech_Recognition = []
++Phone_StartScreen = []
++Phone_System = []
++Phone_System_Power = []
++Phone_System_Profile = []
++Phone_System_UserProfile = []
++Phone_System_UserProfile_GameServices = []
++Phone_System_UserProfile_GameServices_Core = []
++Phone_UI = []
++Phone_UI_Input = []
++Security = []
++Security_Authentication = []
++Security_Authentication_Identity = []
++Security_Authentication_Identity_Core = []
++Security_Authentication_OnlineId = []
++Security_Authentication_Web = []
++Security_Authentication_Web_Core = []
++Security_Authentication_Web_Provider = []
++Security_Authorization = []
++Security_Authorization_AppCapabilityAccess = []
++Security_Credentials = []
++Security_Credentials_UI = []
++Security_Cryptography = []
++Security_Cryptography_Certificates = []
++Security_Cryptography_Core = []
++Security_Cryptography_DataProtection = []
++Security_DataProtection = []
++Security_EnterpriseData = []
++Security_ExchangeActiveSyncProvisioning = []
++Security_Isolation = []
++Services = []
++Services_Maps = []
++Services_Maps_Guidance = []
++Services_Maps_LocalSearch = []
++Services_Maps_OfflineMaps = []
++Services_Store = []
++Services_TargetedContent = []
++Storage = []
++Storage_AccessCache = []
++Storage_BulkAccess = []
++Storage_Compression = []
++Storage_FileProperties = []
++Storage_Pickers = []
++Storage_Pickers_Provider = []
++Storage_Provider = []
++Storage_Search = []
++Storage_Streams = []
++System = []
++System_Diagnostics = []
++System_Diagnostics_DevicePortal = []
++System_Diagnostics_Telemetry = []
++System_Diagnostics_TraceReporting = []
++System_Display = []
++System_Implementation = []
++System_Implementation_FileExplorer = []
++System_Inventory = []
++System_Power = []
++System_Profile = []
++System_Profile_SystemManufacturers = []
++System_RemoteDesktop = []
++System_RemoteDesktop_Input = []
++System_RemoteDesktop_Provider = []
++System_RemoteSystems = []
++System_Threading = []
++System_Threading_Core = []
++System_Update = []
++System_UserProfile = []
++UI = []
++UI_Accessibility = []
++UI_ApplicationSettings = []
++UI_Composition = []
++UI_Composition_Core = []
++UI_Composition_Desktop = []
++UI_Composition_Diagnostics = []
++UI_Composition_Effects = []
++UI_Composition_Interactions = []
++UI_Composition_Scenes = []
++UI_Core = []
++UI_Core_AnimationMetrics = []
++UI_Core_Preview = []
++UI_Input = []
++UI_Input_Core = []
++UI_Input_Inking = []
++UI_Input_Inking_Analysis = []
++UI_Input_Inking_Core = []
++UI_Input_Inking_Preview = []
++UI_Input_Preview = []
++UI_Input_Preview_Injection = []
++UI_Input_Spatial = []
++UI_Notifications = []
++UI_Notifications_Management = []
++UI_Notifications_Preview = []
++UI_Popups = []
++UI_Shell = []
++UI_StartScreen = []
++UI_Text = []
++UI_Text_Core = []
++UI_UIAutomation = []
++UI_UIAutomation_Core = []
++UI_ViewManagement = []
++UI_ViewManagement_Core = []
++UI_WebUI = []
++UI_WebUI_Core = []
++UI_WindowManagement = []
++UI_WindowManagement_Preview = []
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Web = []
++Web_AtomPub = []
++Web_Http = []
++Web_Http_Diagnostics = []
++Web_Http_Filters = []
++Web_Http_Headers = []
++Web_Syndication = []
++Web_UI = []
++Web_UI_Interop = []
++Win32 = []
++Win32_AI = []
++Win32_AI_MachineLearning = []
++Win32_AI_MachineLearning_DirectML = []
++Win32_AI_MachineLearning_WinML = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Data_Xml = []
++Win32_Data_Xml_MsXml = []
++Win32_Data_Xml_XmlLite = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAccess = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_FunctionDiscovery = []
++Win32_Devices_Geolocation = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_ImageAcquisition = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_CompositionSwapchain = []
++Win32_Graphics_DXCore = []
++Win32_Graphics_Direct2D = []
++Win32_Graphics_Direct2D_Common = []
++Win32_Graphics_Direct3D = []
++Win32_Graphics_Direct3D10 = []
++Win32_Graphics_Direct3D11 = []
++Win32_Graphics_Direct3D11on12 = []
++Win32_Graphics_Direct3D12 = []
++Win32_Graphics_Direct3D9 = []
++Win32_Graphics_Direct3D9on12 = []
++Win32_Graphics_Direct3D_Dxc = []
++Win32_Graphics_Direct3D_Fxc = []
++Win32_Graphics_DirectComposition = []
++Win32_Graphics_DirectDraw = []
++Win32_Graphics_DirectManipulation = []
++Win32_Graphics_DirectWrite = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Dxgi = []
++Win32_Graphics_Dxgi_Common = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_Imaging = []
++Win32_Graphics_Imaging_D2D = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_Audio_Apo = []
++Win32_Media_Audio_DirectMusic = []
++Win32_Media_Audio_DirectSound = []
++Win32_Media_Audio_Endpoints = []
++Win32_Media_Audio_XAudio2 = []
++Win32_Media_DeviceManager = []
++Win32_Media_DirectShow = []
++Win32_Media_DirectShow_Tv = []
++Win32_Media_DirectShow_Xml = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_LibrarySharingServices = []
++Win32_Media_MediaFoundation = []
++Win32_Media_MediaPlayer = []
++Win32_Media_Multimedia = []
++Win32_Media_PictureAcquisition = []
++Win32_Media_Speech = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_MobileBroadband = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_NetworkPolicyServer = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectNow = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_BackgroundIntelligentTransferService = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_NetworkListManager = []
++Win32_Networking_RemoteDifferentialCompression = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authentication_Identity_Provider = []
++Win32_Security_Authorization = []
++Win32_Security_Authorization_UI = []
++Win32_Security_ConfigurationSnapin = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_Tpm = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DataDeduplication = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_EnhancedStorage = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileServerResourceManager = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_Packaging_Opc = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_VirtualDiskService = []
++Win32_Storage_Vss = []
++Win32_Storage_Xps = []
++Win32_Storage_Xps_Printing = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_AssessmentTool = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_CallObj = []
++Win32_System_Com_ChannelCredentials = []
++Win32_System_Com_Events = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_UI = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_Contacts = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DesktopSharing = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_ClrProfiling = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_ActiveScript = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Mmc = []
++Win32_System_Ole = []
++Win32_System_ParentalControls = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_RealTimeCommunications = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteAssistance = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_ServerBackup = []
++Win32_System_Services = []
++Win32_System_SettingsManagementInfrastructure = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_SideShow = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_TaskScheduler = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_TransactionServer = []
++Win32_System_UpdateAgent = []
++Win32_System_UpdateAssessment = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WinRT = []
++Win32_System_WinRT_AllJoyn = []
++Win32_System_WinRT_Composition = []
++Win32_System_WinRT_CoreInputView = []
++Win32_System_WinRT_Direct3D11 = []
++Win32_System_WinRT_Display = []
++Win32_System_WinRT_Graphics = []
++Win32_System_WinRT_Graphics_Capture = []
++Win32_System_WinRT_Graphics_Direct2D = []
++Win32_System_WinRT_Graphics_Imaging = []
++Win32_System_WinRT_Holographic = []
++Win32_System_WinRT_Isolation = []
++Win32_System_WinRT_ML = []
++Win32_System_WinRT_Media = []
++Win32_System_WinRT_Metadata = []
++Win32_System_WinRT_Pdf = []
++Win32_System_WinRT_Printing = []
++Win32_System_WinRT_Shell = []
++Win32_System_WinRT_Storage = []
++Win32_System_WindowsProgramming = []
++Win32_System_WindowsSync = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_Animation = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_Controls_RichEdit = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_Ink = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Radial = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_LegacyWindowsEnvironmentFeatures = []
++Win32_UI_Magnification = []
++Win32_UI_Notifications = []
++Win32_UI_Ribbon = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_UI_Wpf = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
+ default = []
+ deprecated = []
+ docs = []
diff --git a/tests/configs/windows-0.54/debian/patches/series b/tests/configs/windows-0.54/debian/patches/series
new file mode 100644 (file)
index 0000000..20d1cc7
--- /dev/null
@@ -0,0 +1 @@
+remove-cycles.patch
diff --git a/tests/configs/windows-0.54/debian/rules b/tests/configs/windows-0.54/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.54/debian/rules.debcargo.hint b/tests/configs/windows-0.54/debian/rules.debcargo.hint
new file mode 100755 (executable)
index 0000000..92c239b
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+       dh_auto_test -- test --all
diff --git a/tests/configs/windows-0.58/debian/changelog b/tests/configs/windows-0.58/debian/changelog
new file mode 100644 (file)
index 0000000..44e099c
--- /dev/null
@@ -0,0 +1,6 @@
+rust-windows-0.54 (0.54.0-1) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package windows 0.54.0 from crates.io using debcargo 2.6.1
+
+ -- Fabian Grünbichler <debian@fabian.gruenbichler.email>  Sat, 6 Jul 2024 21:13:52 +0200
diff --git a/tests/configs/windows-0.58/debian/debcargo.toml b/tests/configs/windows-0.58/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..96a9bd9
--- /dev/null
@@ -0,0 +1,7 @@
+semver_suffix = true
+overlay = "."
+
+[packages.lib]
+test_is_broken = false
+[packages."lib+Win32_Foundation"]
+test_is_broken = false
diff --git a/tests/configs/windows-0.58/debian/patches/remove-cycles.patch b/tests/configs/windows-0.58/debian/patches/remove-cycles.patch
new file mode 100644 (file)
index 0000000..7e2d1f2
--- /dev/null
@@ -0,0 +1,1389 @@
+Index: rust-windows-0.58-0.58.0/Cargo.toml
+===================================================================
+--- rust-windows-0.58-0.58.0.orig/Cargo.toml
++++ rust-windows-0.58-0.58.0/Cargo.toml
+@@ -49,697 +49,697 @@ version = "0.58.0"
+ version = "0.52.6"
+ [features]
+-AI = ["Foundation"]
+-AI_MachineLearning = ["AI"]
+-ApplicationModel = ["Foundation"]
+-ApplicationModel_Activation = ["ApplicationModel"]
+-ApplicationModel_AppExtensions = ["ApplicationModel"]
+-ApplicationModel_AppService = ["ApplicationModel"]
+-ApplicationModel_Appointments = ["ApplicationModel"]
+-ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Background = ["ApplicationModel"]
+-ApplicationModel_Calls = ["ApplicationModel"]
+-ApplicationModel_Calls_Background = ["ApplicationModel_Calls"]
+-ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"]
+-ApplicationModel_Chat = ["ApplicationModel"]
+-ApplicationModel_CommunicationBlocking = ["ApplicationModel"]
+-ApplicationModel_Contacts = ["ApplicationModel"]
+-ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"]
+-ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"]
+-ApplicationModel_ConversationalAgent = ["ApplicationModel"]
+-ApplicationModel_Core = ["ApplicationModel"]
+-ApplicationModel_DataTransfer = ["ApplicationModel"]
+-ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"]
+-ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_Email = ["ApplicationModel"]
+-ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"]
+-ApplicationModel_ExtendedExecution = ["ApplicationModel"]
+-ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"]
+-ApplicationModel_Holographic = ["ApplicationModel"]
+-ApplicationModel_LockScreen = ["ApplicationModel"]
+-ApplicationModel_PackageExtensions = ["ApplicationModel"]
+-ApplicationModel_Payments = ["ApplicationModel"]
+-ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"]
+-ApplicationModel_Preview = ["ApplicationModel"]
+-ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"]
+-ApplicationModel_Resources = ["ApplicationModel"]
+-ApplicationModel_Resources_Core = ["ApplicationModel_Resources"]
+-ApplicationModel_Resources_Management = ["ApplicationModel_Resources"]
+-ApplicationModel_Search = ["ApplicationModel"]
+-ApplicationModel_Search_Core = ["ApplicationModel_Search"]
+-ApplicationModel_UserActivities = ["ApplicationModel"]
+-ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"]
+-ApplicationModel_UserDataAccounts = ["ApplicationModel"]
+-ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataTasks = ["ApplicationModel"]
+-ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"]
+-ApplicationModel_VoiceCommands = ["ApplicationModel"]
+-ApplicationModel_Wallet = ["ApplicationModel"]
+-ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"]
+-Data = ["Foundation"]
+-Data_Html = ["Data"]
+-Data_Json = ["Data"]
+-Data_Pdf = ["Data"]
+-Data_Text = ["Data"]
+-Data_Xml = ["Data"]
+-Data_Xml_Dom = ["Data_Xml"]
+-Data_Xml_Xsl = ["Data_Xml"]
+-Devices = ["Foundation"]
+-Devices_Adc = ["Devices"]
+-Devices_Adc_Provider = ["Devices_Adc"]
+-Devices_Background = ["Devices"]
+-Devices_Bluetooth = ["Devices"]
+-Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Background = ["Devices_Bluetooth"]
+-Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"]
+-Devices_Custom = ["Devices"]
+-Devices_Display = ["Devices"]
+-Devices_Display_Core = ["Devices_Display"]
+-Devices_Enumeration = ["Devices"]
+-Devices_Enumeration_Pnp = ["Devices_Enumeration"]
+-Devices_Geolocation = ["Devices"]
+-Devices_Geolocation_Geofencing = ["Devices_Geolocation"]
+-Devices_Geolocation_Provider = ["Devices_Geolocation"]
+-Devices_Gpio = ["Devices"]
+-Devices_Gpio_Provider = ["Devices_Gpio"]
+-Devices_Haptics = ["Devices"]
+-Devices_HumanInterfaceDevice = ["Devices"]
+-Devices_I2c = ["Devices"]
+-Devices_I2c_Provider = ["Devices_I2c"]
+-Devices_Input = ["Devices"]
+-Devices_Input_Preview = ["Devices_Input"]
+-Devices_Lights = ["Devices"]
+-Devices_Lights_Effects = ["Devices_Lights"]
+-Devices_Midi = ["Devices"]
+-Devices_PointOfService = ["Devices"]
+-Devices_PointOfService_Provider = ["Devices_PointOfService"]
+-Devices_Portable = ["Devices"]
+-Devices_Power = ["Devices"]
+-Devices_Printers = ["Devices"]
+-Devices_Printers_Extensions = ["Devices_Printers"]
+-Devices_Pwm = ["Devices"]
+-Devices_Pwm_Provider = ["Devices_Pwm"]
+-Devices_Radios = ["Devices"]
+-Devices_Scanners = ["Devices"]
+-Devices_Sensors = ["Devices"]
+-Devices_Sensors_Custom = ["Devices_Sensors"]
+-Devices_SerialCommunication = ["Devices"]
+-Devices_SmartCards = ["Devices"]
+-Devices_Sms = ["Devices"]
+-Devices_Spi = ["Devices"]
+-Devices_Spi_Provider = ["Devices_Spi"]
+-Devices_Usb = ["Devices"]
+-Devices_WiFi = ["Devices"]
+-Devices_WiFiDirect = ["Devices"]
+-Devices_WiFiDirect_Services = ["Devices_WiFiDirect"]
+-Embedded = ["Foundation"]
+-Embedded_DeviceLockdown = ["Embedded"]
++AI = []
++AI_MachineLearning = []
++ApplicationModel = []
++ApplicationModel_Activation = []
++ApplicationModel_AppExtensions = []
++ApplicationModel_AppService = []
++ApplicationModel_Appointments = []
++ApplicationModel_Appointments_AppointmentsProvider = []
++ApplicationModel_Appointments_DataProvider = []
++ApplicationModel_Background = []
++ApplicationModel_Calls = []
++ApplicationModel_Calls_Background = []
++ApplicationModel_Calls_Provider = []
++ApplicationModel_Chat = []
++ApplicationModel_CommunicationBlocking = []
++ApplicationModel_Contacts = []
++ApplicationModel_Contacts_DataProvider = []
++ApplicationModel_Contacts_Provider = []
++ApplicationModel_ConversationalAgent = []
++ApplicationModel_Core = []
++ApplicationModel_DataTransfer = []
++ApplicationModel_DataTransfer_DragDrop = []
++ApplicationModel_DataTransfer_DragDrop_Core = []
++ApplicationModel_DataTransfer_ShareTarget = []
++ApplicationModel_Email = []
++ApplicationModel_Email_DataProvider = []
++ApplicationModel_ExtendedExecution = []
++ApplicationModel_ExtendedExecution_Foreground = []
++ApplicationModel_Holographic = []
++ApplicationModel_LockScreen = []
++ApplicationModel_PackageExtensions = []
++ApplicationModel_Payments = []
++ApplicationModel_Payments_Provider = []
++ApplicationModel_Preview = []
++ApplicationModel_Preview_Holographic = []
++ApplicationModel_Preview_InkWorkspace = []
++ApplicationModel_Preview_Notes = []
++ApplicationModel_Resources = []
++ApplicationModel_Resources_Core = []
++ApplicationModel_Resources_Management = []
++ApplicationModel_Search = []
++ApplicationModel_Search_Core = []
++ApplicationModel_UserActivities = []
++ApplicationModel_UserActivities_Core = []
++ApplicationModel_UserDataAccounts = []
++ApplicationModel_UserDataAccounts_Provider = []
++ApplicationModel_UserDataAccounts_SystemAccess = []
++ApplicationModel_UserDataTasks = []
++ApplicationModel_UserDataTasks_DataProvider = []
++ApplicationModel_VoiceCommands = []
++ApplicationModel_Wallet = []
++ApplicationModel_Wallet_System = []
++Data = []
++Data_Html = []
++Data_Json = []
++Data_Pdf = []
++Data_Text = []
++Data_Xml = []
++Data_Xml_Dom = []
++Data_Xml_Xsl = []
++Devices = []
++Devices_Adc = []
++Devices_Adc_Provider = []
++Devices_Background = []
++Devices_Bluetooth = []
++Devices_Bluetooth_Advertisement = []
++Devices_Bluetooth_Background = []
++Devices_Bluetooth_GenericAttributeProfile = []
++Devices_Bluetooth_Rfcomm = []
++Devices_Custom = []
++Devices_Display = []
++Devices_Display_Core = []
++Devices_Enumeration = []
++Devices_Enumeration_Pnp = []
++Devices_Geolocation = []
++Devices_Geolocation_Geofencing = []
++Devices_Geolocation_Provider = []
++Devices_Gpio = []
++Devices_Gpio_Provider = []
++Devices_Haptics = []
++Devices_HumanInterfaceDevice = []
++Devices_I2c = []
++Devices_I2c_Provider = []
++Devices_Input = []
++Devices_Input_Preview = []
++Devices_Lights = []
++Devices_Lights_Effects = []
++Devices_Midi = []
++Devices_PointOfService = []
++Devices_PointOfService_Provider = []
++Devices_Portable = []
++Devices_Power = []
++Devices_Printers = []
++Devices_Printers_Extensions = []
++Devices_Pwm = []
++Devices_Pwm_Provider = []
++Devices_Radios = []
++Devices_Scanners = []
++Devices_Sensors = []
++Devices_Sensors_Custom = []
++Devices_SerialCommunication = []
++Devices_SmartCards = []
++Devices_Sms = []
++Devices_Spi = []
++Devices_Spi_Provider = []
++Devices_Usb = []
++Devices_WiFi = []
++Devices_WiFiDirect = []
++Devices_WiFiDirect_Services = []
++Embedded = []
++Embedded_DeviceLockdown = []
+ Foundation = []
+-Foundation_Collections = ["Foundation"]
+-Foundation_Diagnostics = ["Foundation"]
+-Foundation_Metadata = ["Foundation"]
+-Foundation_Numerics = ["Foundation"]
+-Gaming = ["Foundation"]
+-Gaming_Input = ["Gaming"]
+-Gaming_Input_Custom = ["Gaming_Input"]
+-Gaming_Input_ForceFeedback = ["Gaming_Input"]
+-Gaming_Input_Preview = ["Gaming_Input"]
+-Gaming_Preview = ["Gaming"]
+-Gaming_Preview_GamesEnumeration = ["Gaming_Preview"]
+-Gaming_UI = ["Gaming"]
+-Gaming_XboxLive = ["Gaming"]
+-Gaming_XboxLive_Storage = ["Gaming_XboxLive"]
+-Globalization = ["Foundation"]
+-Globalization_Collation = ["Globalization"]
+-Globalization_DateTimeFormatting = ["Globalization"]
+-Globalization_Fonts = ["Globalization"]
+-Globalization_NumberFormatting = ["Globalization"]
+-Globalization_PhoneNumberFormatting = ["Globalization"]
+-Graphics = ["Foundation"]
+-Graphics_Capture = ["Graphics"]
+-Graphics_DirectX = ["Graphics"]
+-Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"]
+-Graphics_Display = ["Graphics"]
+-Graphics_Display_Core = ["Graphics_Display"]
+-Graphics_Effects = ["Graphics"]
+-Graphics_Holographic = ["Graphics"]
+-Graphics_Imaging = ["Graphics"]
+-Graphics_Printing = ["Graphics"]
+-Graphics_Printing3D = ["Graphics"]
+-Graphics_Printing_OptionDetails = ["Graphics_Printing"]
+-Graphics_Printing_PrintSupport = ["Graphics_Printing"]
+-Graphics_Printing_PrintTicket = ["Graphics_Printing"]
+-Graphics_Printing_Workflow = ["Graphics_Printing"]
+-Management = ["Foundation"]
+-Management_Core = ["Management"]
+-Management_Deployment = ["Management"]
+-Management_Deployment_Preview = ["Management_Deployment"]
+-Management_Policies = ["Management"]
+-Management_Setup = ["Management"]
+-Management_Update = ["Management"]
+-Management_Workplace = ["Management"]
+-Media = ["Foundation"]
+-Media_AppBroadcasting = ["Media"]
+-Media_AppRecording = ["Media"]
+-Media_Audio = ["Media"]
+-Media_Capture = ["Media"]
+-Media_Capture_Core = ["Media_Capture"]
+-Media_Capture_Frames = ["Media_Capture"]
+-Media_Casting = ["Media"]
+-Media_ClosedCaptioning = ["Media"]
+-Media_ContentRestrictions = ["Media"]
+-Media_Control = ["Media"]
+-Media_Core = ["Media"]
+-Media_Core_Preview = ["Media_Core"]
+-Media_Devices = ["Media"]
+-Media_Devices_Core = ["Media_Devices"]
+-Media_DialProtocol = ["Media"]
+-Media_Editing = ["Media"]
+-Media_Effects = ["Media"]
+-Media_FaceAnalysis = ["Media"]
+-Media_Import = ["Media"]
+-Media_MediaProperties = ["Media"]
+-Media_Miracast = ["Media"]
+-Media_Ocr = ["Media"]
+-Media_PlayTo = ["Media"]
+-Media_Playback = ["Media"]
+-Media_Playlists = ["Media"]
+-Media_Protection = ["Media"]
+-Media_Protection_PlayReady = ["Media_Protection"]
+-Media_Render = ["Media"]
+-Media_SpeechRecognition = ["Media"]
+-Media_SpeechSynthesis = ["Media"]
+-Media_Streaming = ["Media"]
+-Media_Streaming_Adaptive = ["Media_Streaming"]
+-Media_Transcoding = ["Media"]
+-Networking = ["Foundation"]
+-Networking_BackgroundTransfer = ["Networking"]
+-Networking_Connectivity = ["Networking"]
+-Networking_NetworkOperators = ["Networking"]
+-Networking_Proximity = ["Networking"]
+-Networking_PushNotifications = ["Networking"]
+-Networking_ServiceDiscovery = ["Networking"]
+-Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"]
+-Networking_Sockets = ["Networking"]
+-Networking_Vpn = ["Networking"]
+-Networking_XboxLive = ["Networking"]
+-Perception = ["Foundation"]
+-Perception_Automation = ["Perception"]
+-Perception_Automation_Core = ["Perception_Automation"]
+-Perception_People = ["Perception"]
+-Perception_Spatial = ["Perception"]
+-Perception_Spatial_Preview = ["Perception_Spatial"]
+-Perception_Spatial_Surfaces = ["Perception_Spatial"]
+-Phone = ["Foundation"]
+-Phone_ApplicationModel = ["Phone"]
+-Phone_Devices = ["Phone"]
+-Phone_Devices_Notification = ["Phone_Devices"]
+-Phone_Devices_Power = ["Phone_Devices"]
+-Phone_Management = ["Phone"]
+-Phone_Management_Deployment = ["Phone_Management"]
+-Phone_Media = ["Phone"]
+-Phone_Media_Devices = ["Phone_Media"]
+-Phone_Notification = ["Phone"]
+-Phone_Notification_Management = ["Phone_Notification"]
+-Phone_PersonalInformation = ["Phone"]
+-Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"]
+-Phone_Speech = ["Phone"]
+-Phone_Speech_Recognition = ["Phone_Speech"]
+-Phone_StartScreen = ["Phone"]
+-Phone_System = ["Phone"]
+-Phone_System_Power = ["Phone_System"]
+-Phone_System_Profile = ["Phone_System"]
+-Phone_System_UserProfile = ["Phone_System"]
+-Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"]
+-Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"]
+-Phone_UI = ["Phone"]
+-Phone_UI_Input = ["Phone_UI"]
+-Security = ["Foundation"]
+-Security_Authentication = ["Security"]
+-Security_Authentication_Identity = ["Security_Authentication"]
+-Security_Authentication_Identity_Core = ["Security_Authentication_Identity"]
+-Security_Authentication_OnlineId = ["Security_Authentication"]
+-Security_Authentication_Web = ["Security_Authentication"]
+-Security_Authentication_Web_Core = ["Security_Authentication_Web"]
+-Security_Authentication_Web_Provider = ["Security_Authentication_Web"]
+-Security_Authorization = ["Security"]
+-Security_Authorization_AppCapabilityAccess = ["Security_Authorization"]
+-Security_Credentials = ["Security"]
+-Security_Credentials_UI = ["Security_Credentials"]
+-Security_Cryptography = ["Security"]
+-Security_Cryptography_Certificates = ["Security_Cryptography"]
+-Security_Cryptography_Core = ["Security_Cryptography"]
+-Security_Cryptography_DataProtection = ["Security_Cryptography"]
+-Security_DataProtection = ["Security"]
+-Security_EnterpriseData = ["Security"]
+-Security_ExchangeActiveSyncProvisioning = ["Security"]
+-Security_Isolation = ["Security"]
+-Services = ["Foundation"]
+-Services_Maps = ["Services"]
+-Services_Maps_Guidance = ["Services_Maps"]
+-Services_Maps_LocalSearch = ["Services_Maps"]
+-Services_Maps_OfflineMaps = ["Services_Maps"]
+-Services_Store = ["Services"]
+-Services_TargetedContent = ["Services"]
+-Storage = ["Foundation"]
+-Storage_AccessCache = ["Storage"]
+-Storage_BulkAccess = ["Storage"]
+-Storage_Compression = ["Storage"]
+-Storage_FileProperties = ["Storage"]
+-Storage_Pickers = ["Storage"]
+-Storage_Pickers_Provider = ["Storage_Pickers"]
+-Storage_Provider = ["Storage"]
+-Storage_Search = ["Storage"]
+-Storage_Streams = ["Storage"]
+-System = ["Foundation"]
+-System_Diagnostics = ["System"]
+-System_Diagnostics_DevicePortal = ["System_Diagnostics"]
+-System_Diagnostics_Telemetry = ["System_Diagnostics"]
+-System_Diagnostics_TraceReporting = ["System_Diagnostics"]
+-System_Display = ["System"]
+-System_Implementation = ["System"]
+-System_Implementation_FileExplorer = ["System_Implementation"]
+-System_Inventory = ["System"]
+-System_Power = ["System"]
+-System_Profile = ["System"]
+-System_Profile_SystemManufacturers = ["System_Profile"]
+-System_RemoteDesktop = ["System"]
+-System_RemoteDesktop_Input = ["System_RemoteDesktop"]
+-System_RemoteDesktop_Provider = ["System_RemoteDesktop"]
+-System_RemoteSystems = ["System"]
+-System_Threading = ["System"]
+-System_Threading_Core = ["System_Threading"]
+-System_Update = ["System"]
+-System_UserProfile = ["System"]
+-UI = ["Foundation"]
+-UI_Accessibility = ["UI"]
+-UI_ApplicationSettings = ["UI"]
+-UI_Composition = ["UI"]
+-UI_Composition_Core = ["UI_Composition"]
+-UI_Composition_Desktop = ["UI_Composition"]
+-UI_Composition_Diagnostics = ["UI_Composition"]
+-UI_Composition_Effects = ["UI_Composition"]
+-UI_Composition_Interactions = ["UI_Composition"]
+-UI_Composition_Scenes = ["UI_Composition"]
+-UI_Core = ["UI"]
+-UI_Core_AnimationMetrics = ["UI_Core"]
+-UI_Core_Preview = ["UI_Core"]
+-UI_Input = ["UI"]
+-UI_Input_Core = ["UI_Input"]
+-UI_Input_Inking = ["UI_Input"]
+-UI_Input_Inking_Analysis = ["UI_Input_Inking"]
+-UI_Input_Inking_Core = ["UI_Input_Inking"]
+-UI_Input_Inking_Preview = ["UI_Input_Inking"]
+-UI_Input_Preview = ["UI_Input"]
+-UI_Input_Preview_Injection = ["UI_Input_Preview"]
+-UI_Input_Spatial = ["UI_Input"]
+-UI_Notifications = ["UI"]
+-UI_Notifications_Management = ["UI_Notifications"]
+-UI_Notifications_Preview = ["UI_Notifications"]
+-UI_Popups = ["UI"]
+-UI_Shell = ["UI"]
+-UI_StartScreen = ["UI"]
+-UI_Text = ["UI"]
+-UI_Text_Core = ["UI_Text"]
+-UI_UIAutomation = ["UI"]
+-UI_UIAutomation_Core = ["UI_UIAutomation"]
+-UI_ViewManagement = ["UI"]
+-UI_ViewManagement_Core = ["UI_ViewManagement"]
+-UI_WebUI = ["UI"]
+-UI_WebUI_Core = ["UI_WebUI"]
+-UI_WindowManagement = ["UI"]
+-UI_WindowManagement_Preview = ["UI_WindowManagement"]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_Bluetooth = ["Wdk_Devices"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_Memory = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Web = ["Foundation"]
+-Web_AtomPub = ["Web"]
+-Web_Http = ["Web"]
+-Web_Http_Diagnostics = ["Web_Http"]
+-Web_Http_Filters = ["Web_Http"]
+-Web_Http_Headers = ["Web_Http"]
+-Web_Syndication = ["Web"]
+-Web_UI = ["Web"]
+-Web_UI_Interop = ["Web_UI"]
+-Win32 = ["Win32_Foundation"]
+-Win32_AI = ["Win32"]
+-Win32_AI_MachineLearning = ["Win32_AI"]
+-Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"]
+-Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Data_Xml = ["Win32_Data"]
+-Win32_Data_Xml_MsXml = ["Win32_Data_Xml"]
+-Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAccess = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_FunctionDiscovery = ["Win32_Devices"]
+-Win32_Devices_Geolocation = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_ImageAcquisition = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"]
+-Win32_Graphics_DXCore = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"]
+-Win32_Graphics_Direct3D = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D10 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_DirectComposition = ["Win32_Graphics"]
+-Win32_Graphics_DirectDraw = ["Win32_Graphics"]
+-Win32_Graphics_DirectManipulation = ["Win32_Graphics"]
+-Win32_Graphics_DirectWrite = ["Win32_Graphics"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_Imaging = ["Win32_Graphics"]
+-Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_Audio_Apo = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"]
+-Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"]
+-Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"]
+-Win32_Media_DeviceManager = ["Win32_Media"]
+-Win32_Media_DirectShow = ["Win32_Media"]
+-Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"]
+-Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_LibrarySharingServices = ["Win32_Media"]
+-Win32_Media_MediaFoundation = ["Win32_Media"]
+-Win32_Media_MediaPlayer = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_PictureAcquisition = ["Win32_Media"]
+-Win32_Media_Speech = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_NetworkListManager = ["Win32_Networking"]
+-Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Authorization_UI = ["Win32_Security_Authorization"]
+-Win32_Security_ConfigurationSnapin = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_Tpm = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DataDeduplication = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_EnhancedStorage = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileServerResourceManager = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_VirtualDiskService = ["Win32_Storage"]
+-Win32_Storage_Vss = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_AssessmentTool = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_CallObj = ["Win32_System_Com"]
+-Win32_System_Com_ChannelCredentials = ["Win32_System_Com"]
+-Win32_System_Com_Events = ["Win32_System_Com"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_UI = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_Contacts = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DesktopSharing = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Mmc = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_ParentalControls = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_RealTimeCommunications = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteAssistance = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_ServerBackup = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SettingsManagementInfrastructure = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_SideShow = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_TaskScheduler = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_TransactionServer = ["Win32_System"]
+-Win32_System_UpdateAgent = ["Win32_System"]
+-Win32_System_UpdateAssessment = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WinRT = ["Win32_System"]
+-Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Composition = ["Win32_System_WinRT"]
+-Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Display = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Holographic = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Isolation = ["Win32_System_WinRT"]
+-Win32_System_WinRT_ML = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Media = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Metadata = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Pdf = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Printing = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Shell = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Storage = ["Win32_System_WinRT"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_WindowsSync = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_Animation = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_Ink = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Radial = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Notifications = ["Win32_UI"]
+-Win32_UI_Ribbon = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_UI_Wpf = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
+-default = ["std"]
++Foundation_Collections = []
++Foundation_Diagnostics = []
++Foundation_Metadata = []
++Foundation_Numerics = []
++Gaming = []
++Gaming_Input = []
++Gaming_Input_Custom = []
++Gaming_Input_ForceFeedback = []
++Gaming_Input_Preview = []
++Gaming_Preview = []
++Gaming_Preview_GamesEnumeration = []
++Gaming_UI = []
++Gaming_XboxLive = []
++Gaming_XboxLive_Storage = []
++Globalization = []
++Globalization_Collation = []
++Globalization_DateTimeFormatting = []
++Globalization_Fonts = []
++Globalization_NumberFormatting = []
++Globalization_PhoneNumberFormatting = []
++Graphics = []
++Graphics_Capture = []
++Graphics_DirectX = []
++Graphics_DirectX_Direct3D11 = []
++Graphics_Display = []
++Graphics_Display_Core = []
++Graphics_Effects = []
++Graphics_Holographic = []
++Graphics_Imaging = []
++Graphics_Printing = []
++Graphics_Printing3D = []
++Graphics_Printing_OptionDetails = []
++Graphics_Printing_PrintSupport = []
++Graphics_Printing_PrintTicket = []
++Graphics_Printing_Workflow = []
++Management = []
++Management_Core = []
++Management_Deployment = []
++Management_Deployment_Preview = []
++Management_Policies = []
++Management_Setup = []
++Management_Update = []
++Management_Workplace = []
++Media = []
++Media_AppBroadcasting = []
++Media_AppRecording = []
++Media_Audio = []
++Media_Capture = []
++Media_Capture_Core = []
++Media_Capture_Frames = []
++Media_Casting = []
++Media_ClosedCaptioning = []
++Media_ContentRestrictions = []
++Media_Control = []
++Media_Core = []
++Media_Core_Preview = []
++Media_Devices = []
++Media_Devices_Core = []
++Media_DialProtocol = []
++Media_Editing = []
++Media_Effects = []
++Media_FaceAnalysis = []
++Media_Import = []
++Media_MediaProperties = []
++Media_Miracast = []
++Media_Ocr = []
++Media_PlayTo = []
++Media_Playback = []
++Media_Playlists = []
++Media_Protection = []
++Media_Protection_PlayReady = []
++Media_Render = []
++Media_SpeechRecognition = []
++Media_SpeechSynthesis = []
++Media_Streaming = []
++Media_Streaming_Adaptive = []
++Media_Transcoding = []
++Networking = []
++Networking_BackgroundTransfer = []
++Networking_Connectivity = []
++Networking_NetworkOperators = []
++Networking_Proximity = []
++Networking_PushNotifications = []
++Networking_ServiceDiscovery = []
++Networking_ServiceDiscovery_Dnssd = []
++Networking_Sockets = []
++Networking_Vpn = []
++Networking_XboxLive = []
++Perception = []
++Perception_Automation = []
++Perception_Automation_Core = []
++Perception_People = []
++Perception_Spatial = []
++Perception_Spatial_Preview = []
++Perception_Spatial_Surfaces = []
++Phone = []
++Phone_ApplicationModel = []
++Phone_Devices = []
++Phone_Devices_Notification = []
++Phone_Devices_Power = []
++Phone_Management = []
++Phone_Management_Deployment = []
++Phone_Media = []
++Phone_Media_Devices = []
++Phone_Notification = []
++Phone_Notification_Management = []
++Phone_PersonalInformation = []
++Phone_PersonalInformation_Provisioning = []
++Phone_Speech = []
++Phone_Speech_Recognition = []
++Phone_StartScreen = []
++Phone_System = []
++Phone_System_Power = []
++Phone_System_Profile = []
++Phone_System_UserProfile = []
++Phone_System_UserProfile_GameServices = []
++Phone_System_UserProfile_GameServices_Core = []
++Phone_UI = []
++Phone_UI_Input = []
++Security = []
++Security_Authentication = []
++Security_Authentication_Identity = []
++Security_Authentication_Identity_Core = []
++Security_Authentication_OnlineId = []
++Security_Authentication_Web = []
++Security_Authentication_Web_Core = []
++Security_Authentication_Web_Provider = []
++Security_Authorization = []
++Security_Authorization_AppCapabilityAccess = []
++Security_Credentials = []
++Security_Credentials_UI = []
++Security_Cryptography = []
++Security_Cryptography_Certificates = []
++Security_Cryptography_Core = []
++Security_Cryptography_DataProtection = []
++Security_DataProtection = []
++Security_EnterpriseData = []
++Security_ExchangeActiveSyncProvisioning = []
++Security_Isolation = []
++Services = []
++Services_Maps = []
++Services_Maps_Guidance = []
++Services_Maps_LocalSearch = []
++Services_Maps_OfflineMaps = []
++Services_Store = []
++Services_TargetedContent = []
++Storage = []
++Storage_AccessCache = []
++Storage_BulkAccess = []
++Storage_Compression = []
++Storage_FileProperties = []
++Storage_Pickers = []
++Storage_Pickers_Provider = []
++Storage_Provider = []
++Storage_Search = []
++Storage_Streams = []
++System = []
++System_Diagnostics = []
++System_Diagnostics_DevicePortal = []
++System_Diagnostics_Telemetry = []
++System_Diagnostics_TraceReporting = []
++System_Display = []
++System_Implementation = []
++System_Implementation_FileExplorer = []
++System_Inventory = []
++System_Power = []
++System_Profile = []
++System_Profile_SystemManufacturers = []
++System_RemoteDesktop = []
++System_RemoteDesktop_Input = []
++System_RemoteDesktop_Provider = []
++System_RemoteSystems = []
++System_Threading = []
++System_Threading_Core = []
++System_Update = []
++System_UserProfile = []
++UI = []
++UI_Accessibility = []
++UI_ApplicationSettings = []
++UI_Composition = []
++UI_Composition_Core = []
++UI_Composition_Desktop = []
++UI_Composition_Diagnostics = []
++UI_Composition_Effects = []
++UI_Composition_Interactions = []
++UI_Composition_Scenes = []
++UI_Core = []
++UI_Core_AnimationMetrics = []
++UI_Core_Preview = []
++UI_Input = []
++UI_Input_Core = []
++UI_Input_Inking = []
++UI_Input_Inking_Analysis = []
++UI_Input_Inking_Core = []
++UI_Input_Inking_Preview = []
++UI_Input_Preview = []
++UI_Input_Preview_Injection = []
++UI_Input_Spatial = []
++UI_Notifications = []
++UI_Notifications_Management = []
++UI_Notifications_Preview = []
++UI_Popups = []
++UI_Shell = []
++UI_StartScreen = []
++UI_Text = []
++UI_Text_Core = []
++UI_UIAutomation = []
++UI_UIAutomation_Core = []
++UI_ViewManagement = []
++UI_ViewManagement_Core = []
++UI_WebUI = []
++UI_WebUI_Core = []
++UI_WindowManagement = []
++UI_WindowManagement_Preview = []
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_Bluetooth = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_Memory = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Web = []
++Web_AtomPub = []
++Web_Http = []
++Web_Http_Diagnostics = []
++Web_Http_Filters = []
++Web_Http_Headers = []
++Web_Syndication = []
++Web_UI = []
++Web_UI_Interop = []
++Win32 = []
++Win32_AI = []
++Win32_AI_MachineLearning = []
++Win32_AI_MachineLearning_DirectML = []
++Win32_AI_MachineLearning_WinML = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Data_Xml = []
++Win32_Data_Xml_MsXml = []
++Win32_Data_Xml_XmlLite = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAccess = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_FunctionDiscovery = []
++Win32_Devices_Geolocation = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_ImageAcquisition = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_CompositionSwapchain = []
++Win32_Graphics_DXCore = []
++Win32_Graphics_Direct2D = []
++Win32_Graphics_Direct2D_Common = []
++Win32_Graphics_Direct3D = []
++Win32_Graphics_Direct3D10 = []
++Win32_Graphics_Direct3D11 = []
++Win32_Graphics_Direct3D11on12 = []
++Win32_Graphics_Direct3D12 = []
++Win32_Graphics_Direct3D9 = []
++Win32_Graphics_Direct3D9on12 = []
++Win32_Graphics_Direct3D_Dxc = []
++Win32_Graphics_Direct3D_Fxc = []
++Win32_Graphics_DirectComposition = []
++Win32_Graphics_DirectDraw = []
++Win32_Graphics_DirectManipulation = []
++Win32_Graphics_DirectWrite = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Dxgi = []
++Win32_Graphics_Dxgi_Common = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_Imaging = []
++Win32_Graphics_Imaging_D2D = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_Audio_Apo = []
++Win32_Media_Audio_DirectMusic = []
++Win32_Media_Audio_DirectSound = []
++Win32_Media_Audio_Endpoints = []
++Win32_Media_Audio_XAudio2 = []
++Win32_Media_DeviceManager = []
++Win32_Media_DirectShow = []
++Win32_Media_DirectShow_Tv = []
++Win32_Media_DirectShow_Xml = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_LibrarySharingServices = []
++Win32_Media_MediaFoundation = []
++Win32_Media_MediaPlayer = []
++Win32_Media_Multimedia = []
++Win32_Media_PictureAcquisition = []
++Win32_Media_Speech = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_MobileBroadband = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_NetworkPolicyServer = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectNow = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_BackgroundIntelligentTransferService = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_NetworkListManager = []
++Win32_Networking_RemoteDifferentialCompression = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authentication_Identity_Provider = []
++Win32_Security_Authorization = []
++Win32_Security_Authorization_UI = []
++Win32_Security_ConfigurationSnapin = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_Tpm = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DataDeduplication = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_EnhancedStorage = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileServerResourceManager = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_Packaging_Opc = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_VirtualDiskService = []
++Win32_Storage_Vss = []
++Win32_Storage_Xps = []
++Win32_Storage_Xps_Printing = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_AssessmentTool = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_CallObj = []
++Win32_System_Com_ChannelCredentials = []
++Win32_System_Com_Events = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_UI = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_Contacts = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DesktopSharing = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_ClrProfiling = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_ActiveScript = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Mmc = []
++Win32_System_Ole = []
++Win32_System_ParentalControls = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_RealTimeCommunications = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteAssistance = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_ServerBackup = []
++Win32_System_Services = []
++Win32_System_SettingsManagementInfrastructure = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_SideShow = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_TaskScheduler = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_TransactionServer = []
++Win32_System_UpdateAgent = []
++Win32_System_UpdateAssessment = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WinRT = []
++Win32_System_WinRT_AllJoyn = []
++Win32_System_WinRT_Composition = []
++Win32_System_WinRT_CoreInputView = []
++Win32_System_WinRT_Direct3D11 = []
++Win32_System_WinRT_Display = []
++Win32_System_WinRT_Graphics = []
++Win32_System_WinRT_Graphics_Capture = []
++Win32_System_WinRT_Graphics_Direct2D = []
++Win32_System_WinRT_Graphics_Imaging = []
++Win32_System_WinRT_Holographic = []
++Win32_System_WinRT_Isolation = []
++Win32_System_WinRT_ML = []
++Win32_System_WinRT_Media = []
++Win32_System_WinRT_Metadata = []
++Win32_System_WinRT_Pdf = []
++Win32_System_WinRT_Printing = []
++Win32_System_WinRT_Shell = []
++Win32_System_WinRT_Storage = []
++Win32_System_WindowsProgramming = []
++Win32_System_WindowsSync = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_Animation = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_Controls_RichEdit = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_Ink = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Radial = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_LegacyWindowsEnvironmentFeatures = []
++Win32_UI_Magnification = []
++Win32_UI_Notifications = []
++Win32_UI_Ribbon = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_UI_Wpf = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
++default = []
+ deprecated = []
+ docs = []
+ implement = []
+-std = ["windows-core/std"]
++std = []
+ [lints.rust]
+ missing_docs = "warn"
diff --git a/tests/configs/windows-0.58/debian/patches/remove-cycles.patch~ b/tests/configs/windows-0.58/debian/patches/remove-cycles.patch~
new file mode 100644 (file)
index 0000000..42f7eb7
--- /dev/null
@@ -0,0 +1,1389 @@
+Index: rust-windows-0.54-0.54.0/Cargo.toml
+===================================================================
+--- rust-windows-0.54-0.54.0.orig/Cargo.toml
++++ rust-windows-0.54-0.54.0/Cargo.toml
+@@ -46,699 +46,696 @@ optional = true
+ version = "0.52.3"
+ [features]
+-AI = ["Foundation"]
+-AI_MachineLearning = ["AI"]
+-ApplicationModel = ["Foundation"]
+-ApplicationModel_Activation = ["ApplicationModel"]
+-ApplicationModel_AppExtensions = ["ApplicationModel"]
+-ApplicationModel_AppService = ["ApplicationModel"]
+-ApplicationModel_Appointments = ["ApplicationModel"]
+-ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"]
+-ApplicationModel_Background = ["ApplicationModel"]
+-ApplicationModel_Calls = ["ApplicationModel"]
+-ApplicationModel_Calls_Background = ["ApplicationModel_Calls"]
+-ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"]
+-ApplicationModel_Chat = ["ApplicationModel"]
+-ApplicationModel_CommunicationBlocking = ["ApplicationModel"]
+-ApplicationModel_Contacts = ["ApplicationModel"]
+-ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"]
+-ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"]
+-ApplicationModel_ConversationalAgent = ["ApplicationModel"]
+-ApplicationModel_Core = ["ApplicationModel"]
+-ApplicationModel_DataTransfer = ["ApplicationModel"]
+-ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"]
+-ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"]
+-ApplicationModel_Email = ["ApplicationModel"]
+-ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"]
+-ApplicationModel_ExtendedExecution = ["ApplicationModel"]
+-ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"]
+-ApplicationModel_Holographic = ["ApplicationModel"]
+-ApplicationModel_LockScreen = ["ApplicationModel"]
+-ApplicationModel_Payments = ["ApplicationModel"]
+-ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"]
+-ApplicationModel_Preview = ["ApplicationModel"]
+-ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"]
+-ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"]
+-ApplicationModel_Resources = ["ApplicationModel"]
+-ApplicationModel_Resources_Core = ["ApplicationModel_Resources"]
+-ApplicationModel_Resources_Management = ["ApplicationModel_Resources"]
+-ApplicationModel_Search = ["ApplicationModel"]
+-ApplicationModel_Search_Core = ["ApplicationModel_Search"]
+-ApplicationModel_Store = ["ApplicationModel"]
+-ApplicationModel_Store_LicenseManagement = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview = ["ApplicationModel_Store"]
+-ApplicationModel_Store_Preview_InstallControl = ["ApplicationModel_Store_Preview"]
+-ApplicationModel_UserActivities = ["ApplicationModel"]
+-ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"]
+-ApplicationModel_UserDataAccounts = ["ApplicationModel"]
+-ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"]
+-ApplicationModel_UserDataTasks = ["ApplicationModel"]
+-ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"]
+-ApplicationModel_VoiceCommands = ["ApplicationModel"]
+-ApplicationModel_Wallet = ["ApplicationModel"]
+-ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"]
+-Data = ["Foundation"]
+-Data_Html = ["Data"]
+-Data_Json = ["Data"]
+-Data_Pdf = ["Data"]
+-Data_Text = ["Data"]
+-Data_Xml = ["Data"]
+-Data_Xml_Dom = ["Data_Xml"]
+-Data_Xml_Xsl = ["Data_Xml"]
+-Devices = ["Foundation"]
+-Devices_Adc = ["Devices"]
+-Devices_Adc_Provider = ["Devices_Adc"]
+-Devices_Background = ["Devices"]
+-Devices_Bluetooth = ["Devices"]
+-Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Background = ["Devices_Bluetooth"]
+-Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"]
+-Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"]
+-Devices_Custom = ["Devices"]
+-Devices_Display = ["Devices"]
+-Devices_Display_Core = ["Devices_Display"]
+-Devices_Enumeration = ["Devices"]
+-Devices_Enumeration_Pnp = ["Devices_Enumeration"]
+-Devices_Geolocation = ["Devices"]
+-Devices_Geolocation_Geofencing = ["Devices_Geolocation"]
+-Devices_Geolocation_Provider = ["Devices_Geolocation"]
+-Devices_Gpio = ["Devices"]
+-Devices_Gpio_Provider = ["Devices_Gpio"]
+-Devices_Haptics = ["Devices"]
+-Devices_HumanInterfaceDevice = ["Devices"]
+-Devices_I2c = ["Devices"]
+-Devices_I2c_Provider = ["Devices_I2c"]
+-Devices_Input = ["Devices"]
+-Devices_Input_Preview = ["Devices_Input"]
+-Devices_Lights = ["Devices"]
+-Devices_Lights_Effects = ["Devices_Lights"]
+-Devices_Midi = ["Devices"]
+-Devices_PointOfService = ["Devices"]
+-Devices_PointOfService_Provider = ["Devices_PointOfService"]
+-Devices_Portable = ["Devices"]
+-Devices_Power = ["Devices"]
+-Devices_Printers = ["Devices"]
+-Devices_Printers_Extensions = ["Devices_Printers"]
+-Devices_Pwm = ["Devices"]
+-Devices_Pwm_Provider = ["Devices_Pwm"]
+-Devices_Radios = ["Devices"]
+-Devices_Scanners = ["Devices"]
+-Devices_Sensors = ["Devices"]
+-Devices_Sensors_Custom = ["Devices_Sensors"]
+-Devices_SerialCommunication = ["Devices"]
+-Devices_SmartCards = ["Devices"]
+-Devices_Sms = ["Devices"]
+-Devices_Spi = ["Devices"]
+-Devices_Spi_Provider = ["Devices_Spi"]
+-Devices_Usb = ["Devices"]
+-Devices_WiFi = ["Devices"]
+-Devices_WiFiDirect = ["Devices"]
+-Devices_WiFiDirect_Services = ["Devices_WiFiDirect"]
+-Embedded = ["Foundation"]
+-Embedded_DeviceLockdown = ["Embedded"]
++AI = []
++AI_MachineLearning = []
++ApplicationModel = []
++ApplicationModel_Activation = []
++ApplicationModel_AppExtensions = []
++ApplicationModel_AppService = []
++ApplicationModel_Appointments = []
++ApplicationModel_Appointments_AppointmentsProvider = []
++ApplicationModel_Appointments_DataProvider = []
++ApplicationModel_Background = []
++ApplicationModel_Calls = []
++ApplicationModel_Calls_Background = []
++ApplicationModel_Calls_Provider = []
++ApplicationModel_Chat = []
++ApplicationModel_CommunicationBlocking = []
++ApplicationModel_Contacts = []
++ApplicationModel_Contacts_DataProvider = []
++ApplicationModel_Contacts_Provider = []
++ApplicationModel_ConversationalAgent = []
++ApplicationModel_Core = []
++ApplicationModel_DataTransfer = []
++ApplicationModel_DataTransfer_DragDrop = []
++ApplicationModel_DataTransfer_DragDrop_Core = []
++ApplicationModel_DataTransfer_ShareTarget = []
++ApplicationModel_Email = []
++ApplicationModel_Email_DataProvider = []
++ApplicationModel_ExtendedExecution = []
++ApplicationModel_ExtendedExecution_Foreground = []
++ApplicationModel_Holographic = []
++ApplicationModel_LockScreen = []
++ApplicationModel_Payments = []
++ApplicationModel_Payments_Provider = []
++ApplicationModel_Preview = []
++ApplicationModel_Preview_Holographic = []
++ApplicationModel_Preview_InkWorkspace = []
++ApplicationModel_Preview_Notes = []
++ApplicationModel_Resources = []
++ApplicationModel_Resources_Core = []
++ApplicationModel_Resources_Management = []
++ApplicationModel_Search = []
++ApplicationModel_Search_Core = []
++ApplicationModel_Store = []
++ApplicationModel_Store_LicenseManagement = []
++ApplicationModel_Store_Preview = []
++ApplicationModel_Store_Preview_InstallControl = []
++ApplicationModel_UserActivities = []
++ApplicationModel_UserActivities_Core = []
++ApplicationModel_UserDataAccounts = []
++ApplicationModel_UserDataAccounts_Provider = []
++ApplicationModel_UserDataAccounts_SystemAccess = []
++ApplicationModel_UserDataTasks = []
++ApplicationModel_UserDataTasks_DataProvider = []
++ApplicationModel_VoiceCommands = []
++ApplicationModel_Wallet = []
++ApplicationModel_Wallet_System = []
++Data = []
++Data_Html = []
++Data_Json = []
++Data_Pdf = []
++Data_Text = []
++Data_Xml = []
++Data_Xml_Dom = []
++Data_Xml_Xsl = []
++Devices = []
++Devices_Adc = []
++Devices_Adc_Provider = []
++Devices_Background = []
++Devices_Bluetooth = []
++Devices_Bluetooth_Advertisement = []
++Devices_Bluetooth_Background = []
++Devices_Bluetooth_GenericAttributeProfile = []
++Devices_Bluetooth_Rfcomm = []
++Devices_Custom = []
++Devices_Display = []
++Devices_Display_Core = []
++Devices_Enumeration = []
++Devices_Enumeration_Pnp = []
++Devices_Geolocation = []
++Devices_Geolocation_Geofencing = []
++Devices_Geolocation_Provider = []
++Devices_Gpio = []
++Devices_Gpio_Provider = []
++Devices_Haptics = []
++Devices_HumanInterfaceDevice = []
++Devices_I2c = []
++Devices_I2c_Provider = []
++Devices_Input = []
++Devices_Input_Preview = []
++Devices_Lights = []
++Devices_Lights_Effects = []
++Devices_Midi = []
++Devices_PointOfService = []
++Devices_PointOfService_Provider = []
++Devices_Portable = []
++Devices_Power = []
++Devices_Printers = []
++Devices_Printers_Extensions = []
++Devices_Pwm = []
++Devices_Pwm_Provider = []
++Devices_Radios = []
++Devices_Scanners = []
++Devices_Sensors = []
++Devices_Sensors_Custom = []
++Devices_SerialCommunication = []
++Devices_SmartCards = []
++Devices_Sms = []
++Devices_Spi = []
++Devices_Spi_Provider = []
++Devices_Usb = []
++Devices_WiFi = []
++Devices_WiFiDirect = []
++Devices_WiFiDirect_Services = []
++Embedded = []
++Embedded_DeviceLockdown = []
+ Foundation = []
+-Foundation_Collections = ["Foundation"]
+-Foundation_Diagnostics = ["Foundation"]
+-Foundation_Metadata = ["Foundation"]
+-Foundation_Numerics = ["Foundation"]
+-Gaming = ["Foundation"]
+-Gaming_Input = ["Gaming"]
+-Gaming_Input_Custom = ["Gaming_Input"]
+-Gaming_Input_ForceFeedback = ["Gaming_Input"]
+-Gaming_Input_Preview = ["Gaming_Input"]
+-Gaming_Preview = ["Gaming"]
+-Gaming_Preview_GamesEnumeration = ["Gaming_Preview"]
+-Gaming_UI = ["Gaming"]
+-Gaming_XboxLive = ["Gaming"]
+-Gaming_XboxLive_Storage = ["Gaming_XboxLive"]
+-Globalization = ["Foundation"]
+-Globalization_Collation = ["Globalization"]
+-Globalization_DateTimeFormatting = ["Globalization"]
+-Globalization_Fonts = ["Globalization"]
+-Globalization_NumberFormatting = ["Globalization"]
+-Globalization_PhoneNumberFormatting = ["Globalization"]
+-Graphics = ["Foundation"]
+-Graphics_Capture = ["Graphics"]
+-Graphics_DirectX = ["Graphics"]
+-Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"]
+-Graphics_Display = ["Graphics"]
+-Graphics_Display_Core = ["Graphics_Display"]
+-Graphics_Effects = ["Graphics"]
+-Graphics_Holographic = ["Graphics"]
+-Graphics_Imaging = ["Graphics"]
+-Graphics_Printing = ["Graphics"]
+-Graphics_Printing3D = ["Graphics"]
+-Graphics_Printing_OptionDetails = ["Graphics_Printing"]
+-Graphics_Printing_PrintSupport = ["Graphics_Printing"]
+-Graphics_Printing_PrintTicket = ["Graphics_Printing"]
+-Graphics_Printing_Workflow = ["Graphics_Printing"]
+-Management = ["Foundation"]
+-Management_Core = ["Management"]
+-Management_Deployment = ["Management"]
+-Management_Deployment_Preview = ["Management_Deployment"]
+-Management_Policies = ["Management"]
+-Management_Update = ["Management"]
+-Management_Workplace = ["Management"]
+-Media = ["Foundation"]
+-Media_AppBroadcasting = ["Media"]
+-Media_AppRecording = ["Media"]
+-Media_Audio = ["Media"]
+-Media_Capture = ["Media"]
+-Media_Capture_Core = ["Media_Capture"]
+-Media_Capture_Frames = ["Media_Capture"]
+-Media_Casting = ["Media"]
+-Media_ClosedCaptioning = ["Media"]
+-Media_ContentRestrictions = ["Media"]
+-Media_Control = ["Media"]
+-Media_Core = ["Media"]
+-Media_Core_Preview = ["Media_Core"]
+-Media_Devices = ["Media"]
+-Media_Devices_Core = ["Media_Devices"]
+-Media_DialProtocol = ["Media"]
+-Media_Editing = ["Media"]
+-Media_Effects = ["Media"]
+-Media_FaceAnalysis = ["Media"]
+-Media_Import = ["Media"]
+-Media_MediaProperties = ["Media"]
+-Media_Miracast = ["Media"]
+-Media_Ocr = ["Media"]
+-Media_PlayTo = ["Media"]
+-Media_Playback = ["Media"]
+-Media_Playlists = ["Media"]
+-Media_Protection = ["Media"]
+-Media_Protection_PlayReady = ["Media_Protection"]
+-Media_Render = ["Media"]
+-Media_SpeechRecognition = ["Media"]
+-Media_SpeechSynthesis = ["Media"]
+-Media_Streaming = ["Media"]
+-Media_Streaming_Adaptive = ["Media_Streaming"]
+-Media_Transcoding = ["Media"]
+-Networking = ["Foundation"]
+-Networking_BackgroundTransfer = ["Networking"]
+-Networking_Connectivity = ["Networking"]
+-Networking_NetworkOperators = ["Networking"]
+-Networking_Proximity = ["Networking"]
+-Networking_PushNotifications = ["Networking"]
+-Networking_ServiceDiscovery = ["Networking"]
+-Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"]
+-Networking_Sockets = ["Networking"]
+-Networking_Vpn = ["Networking"]
+-Networking_XboxLive = ["Networking"]
+-Perception = ["Foundation"]
+-Perception_Automation = ["Perception"]
+-Perception_Automation_Core = ["Perception_Automation"]
+-Perception_People = ["Perception"]
+-Perception_Spatial = ["Perception"]
+-Perception_Spatial_Preview = ["Perception_Spatial"]
+-Perception_Spatial_Surfaces = ["Perception_Spatial"]
+-Phone = ["Foundation"]
+-Phone_ApplicationModel = ["Phone"]
+-Phone_Devices = ["Phone"]
+-Phone_Devices_Notification = ["Phone_Devices"]
+-Phone_Devices_Power = ["Phone_Devices"]
+-Phone_Management = ["Phone"]
+-Phone_Management_Deployment = ["Phone_Management"]
+-Phone_Media = ["Phone"]
+-Phone_Media_Devices = ["Phone_Media"]
+-Phone_Notification = ["Phone"]
+-Phone_Notification_Management = ["Phone_Notification"]
+-Phone_PersonalInformation = ["Phone"]
+-Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"]
+-Phone_Speech = ["Phone"]
+-Phone_Speech_Recognition = ["Phone_Speech"]
+-Phone_StartScreen = ["Phone"]
+-Phone_System = ["Phone"]
+-Phone_System_Power = ["Phone_System"]
+-Phone_System_Profile = ["Phone_System"]
+-Phone_System_UserProfile = ["Phone_System"]
+-Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"]
+-Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"]
+-Phone_UI = ["Phone"]
+-Phone_UI_Input = ["Phone_UI"]
+-Security = ["Foundation"]
+-Security_Authentication = ["Security"]
+-Security_Authentication_Identity = ["Security_Authentication"]
+-Security_Authentication_Identity_Core = ["Security_Authentication_Identity"]
+-Security_Authentication_OnlineId = ["Security_Authentication"]
+-Security_Authentication_Web = ["Security_Authentication"]
+-Security_Authentication_Web_Core = ["Security_Authentication_Web"]
+-Security_Authentication_Web_Provider = ["Security_Authentication_Web"]
+-Security_Authorization = ["Security"]
+-Security_Authorization_AppCapabilityAccess = ["Security_Authorization"]
+-Security_Credentials = ["Security"]
+-Security_Credentials_UI = ["Security_Credentials"]
+-Security_Cryptography = ["Security"]
+-Security_Cryptography_Certificates = ["Security_Cryptography"]
+-Security_Cryptography_Core = ["Security_Cryptography"]
+-Security_Cryptography_DataProtection = ["Security_Cryptography"]
+-Security_DataProtection = ["Security"]
+-Security_EnterpriseData = ["Security"]
+-Security_ExchangeActiveSyncProvisioning = ["Security"]
+-Security_Isolation = ["Security"]
+-Services = ["Foundation"]
+-Services_Maps = ["Services"]
+-Services_Maps_Guidance = ["Services_Maps"]
+-Services_Maps_LocalSearch = ["Services_Maps"]
+-Services_Maps_OfflineMaps = ["Services_Maps"]
+-Services_Store = ["Services"]
+-Services_TargetedContent = ["Services"]
+-Storage = ["Foundation"]
+-Storage_AccessCache = ["Storage"]
+-Storage_BulkAccess = ["Storage"]
+-Storage_Compression = ["Storage"]
+-Storage_FileProperties = ["Storage"]
+-Storage_Pickers = ["Storage"]
+-Storage_Pickers_Provider = ["Storage_Pickers"]
+-Storage_Provider = ["Storage"]
+-Storage_Search = ["Storage"]
+-Storage_Streams = ["Storage"]
+-System = ["Foundation"]
+-System_Diagnostics = ["System"]
+-System_Diagnostics_DevicePortal = ["System_Diagnostics"]
+-System_Diagnostics_Telemetry = ["System_Diagnostics"]
+-System_Diagnostics_TraceReporting = ["System_Diagnostics"]
+-System_Display = ["System"]
+-System_Implementation = ["System"]
+-System_Implementation_FileExplorer = ["System_Implementation"]
+-System_Inventory = ["System"]
+-System_Power = ["System"]
+-System_Profile = ["System"]
+-System_Profile_SystemManufacturers = ["System_Profile"]
+-System_RemoteDesktop = ["System"]
+-System_RemoteDesktop_Input = ["System_RemoteDesktop"]
+-System_RemoteDesktop_Provider = ["System_RemoteDesktop"]
+-System_RemoteSystems = ["System"]
+-System_Threading = ["System"]
+-System_Threading_Core = ["System_Threading"]
+-System_Update = ["System"]
+-System_UserProfile = ["System"]
+-UI = ["Foundation"]
+-UI_Accessibility = ["UI"]
+-UI_ApplicationSettings = ["UI"]
+-UI_Composition = ["UI"]
+-UI_Composition_Core = ["UI_Composition"]
+-UI_Composition_Desktop = ["UI_Composition"]
+-UI_Composition_Diagnostics = ["UI_Composition"]
+-UI_Composition_Effects = ["UI_Composition"]
+-UI_Composition_Interactions = ["UI_Composition"]
+-UI_Composition_Scenes = ["UI_Composition"]
+-UI_Core = ["UI"]
+-UI_Core_AnimationMetrics = ["UI_Core"]
+-UI_Core_Preview = ["UI_Core"]
+-UI_Input = ["UI"]
+-UI_Input_Core = ["UI_Input"]
+-UI_Input_Inking = ["UI_Input"]
+-UI_Input_Inking_Analysis = ["UI_Input_Inking"]
+-UI_Input_Inking_Core = ["UI_Input_Inking"]
+-UI_Input_Inking_Preview = ["UI_Input_Inking"]
+-UI_Input_Preview = ["UI_Input"]
+-UI_Input_Preview_Injection = ["UI_Input_Preview"]
+-UI_Input_Spatial = ["UI_Input"]
+-UI_Notifications = ["UI"]
+-UI_Notifications_Management = ["UI_Notifications"]
+-UI_Notifications_Preview = ["UI_Notifications"]
+-UI_Popups = ["UI"]
+-UI_Shell = ["UI"]
+-UI_StartScreen = ["UI"]
+-UI_Text = ["UI"]
+-UI_Text_Core = ["UI_Text"]
+-UI_UIAutomation = ["UI"]
+-UI_UIAutomation_Core = ["UI_UIAutomation"]
+-UI_ViewManagement = ["UI"]
+-UI_ViewManagement_Core = ["UI_ViewManagement"]
+-UI_WebUI = ["UI"]
+-UI_WebUI_Core = ["UI_WebUI"]
+-UI_WindowManagement = ["UI"]
+-UI_WindowManagement_Preview = ["UI_WindowManagement"]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Web = ["Foundation"]
+-Web_AtomPub = ["Web"]
+-Web_Http = ["Web"]
+-Web_Http_Diagnostics = ["Web_Http"]
+-Web_Http_Filters = ["Web_Http"]
+-Web_Http_Headers = ["Web_Http"]
+-Web_Syndication = ["Web"]
+-Web_UI = ["Web"]
+-Web_UI_Interop = ["Web_UI"]
+-Win32 = ["Win32_Foundation"]
+-Win32_AI = ["Win32"]
+-Win32_AI_MachineLearning = ["Win32_AI"]
+-Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"]
+-Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Data_Xml = ["Win32_Data"]
+-Win32_Data_Xml_MsXml = ["Win32_Data_Xml"]
+-Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAccess = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_FunctionDiscovery = ["Win32_Devices"]
+-Win32_Devices_Geolocation = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_ImageAcquisition = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"]
+-Win32_Graphics_DXCore = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D = ["Win32_Graphics"]
+-Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"]
+-Win32_Graphics_Direct3D = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D10 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"]
+-Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"]
+-Win32_Graphics_DirectComposition = ["Win32_Graphics"]
+-Win32_Graphics_DirectDraw = ["Win32_Graphics"]
+-Win32_Graphics_DirectManipulation = ["Win32_Graphics"]
+-Win32_Graphics_DirectWrite = ["Win32_Graphics"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi = ["Win32_Graphics"]
+-Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_Imaging = ["Win32_Graphics"]
+-Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_Audio_Apo = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"]
+-Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"]
+-Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"]
+-Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"]
+-Win32_Media_DeviceManager = ["Win32_Media"]
+-Win32_Media_DirectShow = ["Win32_Media"]
+-Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"]
+-Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_LibrarySharingServices = ["Win32_Media"]
+-Win32_Media_MediaFoundation = ["Win32_Media"]
+-Win32_Media_MediaPlayer = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_PictureAcquisition = ["Win32_Media"]
+-Win32_Media_Speech = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_NetworkListManager = ["Win32_Networking"]
+-Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Authorization_UI = ["Win32_Security_Authorization"]
+-Win32_Security_ConfigurationSnapin = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_Tpm = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DataDeduplication = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_EnhancedStorage = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileServerResourceManager = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_VirtualDiskService = ["Win32_Storage"]
+-Win32_Storage_Vss = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_AssessmentTool = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_CallObj = ["Win32_System_Com"]
+-Win32_System_Com_ChannelCredentials = ["Win32_System_Com"]
+-Win32_System_Com_Events = ["Win32_System_Com"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_UI = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_Contacts = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DesktopSharing = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Mmc = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_ParentalControls = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_RealTimeCommunications = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteAssistance = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_ServerBackup = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SettingsManagementInfrastructure = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_SideShow = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_TaskScheduler = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_TransactionServer = ["Win32_System"]
+-Win32_System_UpdateAgent = ["Win32_System"]
+-Win32_System_UpdateAssessment = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WinRT = ["Win32_System"]
+-Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Composition = ["Win32_System_WinRT"]
+-Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Display = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"]
+-Win32_System_WinRT_Holographic = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Isolation = ["Win32_System_WinRT"]
+-Win32_System_WinRT_ML = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Media = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Metadata = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Pdf = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Printing = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Shell = ["Win32_System_WinRT"]
+-Win32_System_WinRT_Storage = ["Win32_System_WinRT"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_WindowsSync = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_Animation = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_Ink = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Radial = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Notifications = ["Win32_UI"]
+-Win32_UI_Ribbon = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_UI_Wpf = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
++Foundation_Collections = []
++Foundation_Diagnostics = []
++Foundation_Metadata = []
++Foundation_Numerics = []
++Gaming = []
++Gaming_Input = []
++Gaming_Input_Custom = []
++Gaming_Input_ForceFeedback = []
++Gaming_Input_Preview = []
++Gaming_Preview = []
++Gaming_Preview_GamesEnumeration = []
++Gaming_UI = []
++Gaming_XboxLive = []
++Gaming_XboxLive_Storage = []
++Globalization = []
++Globalization_Collation = []
++Globalization_DateTimeFormatting = []
++Globalization_Fonts = []
++Globalization_NumberFormatting = []
++Globalization_PhoneNumberFormatting = []
++Graphics = []
++Graphics_Capture = []
++Graphics_DirectX = []
++Graphics_DirectX_Direct3D11 = []
++Graphics_Display = []
++Graphics_Display_Core = []
++Graphics_Effects = []
++Graphics_Holographic = []
++Graphics_Imaging = []
++Graphics_Printing = []
++Graphics_Printing3D = []
++Graphics_Printing_OptionDetails = []
++Graphics_Printing_PrintSupport = []
++Graphics_Printing_PrintTicket = []
++Graphics_Printing_Workflow = []
++Management = []
++Management_Core = []
++Management_Deployment = []
++Management_Deployment_Preview = []
++Management_Policies = []
++Management_Update = []
++Management_Workplace = []
++Media = []
++Media_AppBroadcasting = []
++Media_AppRecording = []
++Media_Audio = []
++Media_Capture = []
++Media_Capture_Core = []
++Media_Capture_Frames = []
++Media_Casting = []
++Media_ClosedCaptioning = []
++Media_ContentRestrictions = []
++Media_Control = []
++Media_Core = []
++Media_Core_Preview = []
++Media_Devices = []
++Media_Devices_Core = []
++Media_DialProtocol = []
++Media_Editing = []
++Media_Effects = []
++Media_FaceAnalysis = []
++Media_Import = []
++Media_MediaProperties = []
++Media_Miracast = []
++Media_Ocr = []
++Media_PlayTo = []
++Media_Playback = []
++Media_Playlists = []
++Media_Protection = []
++Media_Protection_PlayReady = []
++Media_Render = []
++Media_SpeechRecognition = []
++Media_SpeechSynthesis = []
++Media_Streaming = []
++Media_Streaming_Adaptive = []
++Media_Transcoding = []
++Networking = []
++Networking_BackgroundTransfer = []
++Networking_Connectivity = []
++Networking_NetworkOperators = []
++Networking_Proximity = []
++Networking_PushNotifications = []
++Networking_ServiceDiscovery = []
++Networking_ServiceDiscovery_Dnssd = []
++Networking_Sockets = []
++Networking_Vpn = []
++Networking_XboxLive = []
++Perception = []
++Perception_Automation = []
++Perception_Automation_Core = []
++Perception_People = []
++Perception_Spatial = []
++Perception_Spatial_Preview = []
++Perception_Spatial_Surfaces = []
++Phone = []
++Phone_ApplicationModel = []
++Phone_Devices = []
++Phone_Devices_Notification = []
++Phone_Devices_Power = []
++Phone_Management = []
++Phone_Management_Deployment = []
++Phone_Media = []
++Phone_Media_Devices = []
++Phone_Notification = []
++Phone_Notification_Management = []
++Phone_PersonalInformation = []
++Phone_PersonalInformation_Provisioning = []
++Phone_Speech = []
++Phone_Speech_Recognition = []
++Phone_StartScreen = []
++Phone_System = []
++Phone_System_Power = []
++Phone_System_Profile = []
++Phone_System_UserProfile = []
++Phone_System_UserProfile_GameServices = []
++Phone_System_UserProfile_GameServices_Core = []
++Phone_UI = []
++Phone_UI_Input = []
++Security = []
++Security_Authentication = []
++Security_Authentication_Identity = []
++Security_Authentication_Identity_Core = []
++Security_Authentication_OnlineId = []
++Security_Authentication_Web = []
++Security_Authentication_Web_Core = []
++Security_Authentication_Web_Provider = []
++Security_Authorization = []
++Security_Authorization_AppCapabilityAccess = []
++Security_Credentials = []
++Security_Credentials_UI = []
++Security_Cryptography = []
++Security_Cryptography_Certificates = []
++Security_Cryptography_Core = []
++Security_Cryptography_DataProtection = []
++Security_DataProtection = []
++Security_EnterpriseData = []
++Security_ExchangeActiveSyncProvisioning = []
++Security_Isolation = []
++Services = []
++Services_Maps = []
++Services_Maps_Guidance = []
++Services_Maps_LocalSearch = []
++Services_Maps_OfflineMaps = []
++Services_Store = []
++Services_TargetedContent = []
++Storage = []
++Storage_AccessCache = []
++Storage_BulkAccess = []
++Storage_Compression = []
++Storage_FileProperties = []
++Storage_Pickers = []
++Storage_Pickers_Provider = []
++Storage_Provider = []
++Storage_Search = []
++Storage_Streams = []
++System = []
++System_Diagnostics = []
++System_Diagnostics_DevicePortal = []
++System_Diagnostics_Telemetry = []
++System_Diagnostics_TraceReporting = []
++System_Display = []
++System_Implementation = []
++System_Implementation_FileExplorer = []
++System_Inventory = []
++System_Power = []
++System_Profile = []
++System_Profile_SystemManufacturers = []
++System_RemoteDesktop = []
++System_RemoteDesktop_Input = []
++System_RemoteDesktop_Provider = []
++System_RemoteSystems = []
++System_Threading = []
++System_Threading_Core = []
++System_Update = []
++System_UserProfile = []
++UI = []
++UI_Accessibility = []
++UI_ApplicationSettings = []
++UI_Composition = []
++UI_Composition_Core = []
++UI_Composition_Desktop = []
++UI_Composition_Diagnostics = []
++UI_Composition_Effects = []
++UI_Composition_Interactions = []
++UI_Composition_Scenes = []
++UI_Core = []
++UI_Core_AnimationMetrics = []
++UI_Core_Preview = []
++UI_Input = []
++UI_Input_Core = []
++UI_Input_Inking = []
++UI_Input_Inking_Analysis = []
++UI_Input_Inking_Core = []
++UI_Input_Inking_Preview = []
++UI_Input_Preview = []
++UI_Input_Preview_Injection = []
++UI_Input_Spatial = []
++UI_Notifications = []
++UI_Notifications_Management = []
++UI_Notifications_Preview = []
++UI_Popups = []
++UI_Shell = []
++UI_StartScreen = []
++UI_Text = []
++UI_Text_Core = []
++UI_UIAutomation = []
++UI_UIAutomation_Core = []
++UI_ViewManagement = []
++UI_ViewManagement_Core = []
++UI_WebUI = []
++UI_WebUI_Core = []
++UI_WindowManagement = []
++UI_WindowManagement_Preview = []
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Web = []
++Web_AtomPub = []
++Web_Http = []
++Web_Http_Diagnostics = []
++Web_Http_Filters = []
++Web_Http_Headers = []
++Web_Syndication = []
++Web_UI = []
++Web_UI_Interop = []
++Win32 = []
++Win32_AI = []
++Win32_AI_MachineLearning = []
++Win32_AI_MachineLearning_DirectML = []
++Win32_AI_MachineLearning_WinML = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Data_Xml = []
++Win32_Data_Xml_MsXml = []
++Win32_Data_Xml_XmlLite = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAccess = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_FunctionDiscovery = []
++Win32_Devices_Geolocation = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_ImageAcquisition = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_CompositionSwapchain = []
++Win32_Graphics_DXCore = []
++Win32_Graphics_Direct2D = []
++Win32_Graphics_Direct2D_Common = []
++Win32_Graphics_Direct3D = []
++Win32_Graphics_Direct3D10 = []
++Win32_Graphics_Direct3D11 = []
++Win32_Graphics_Direct3D11on12 = []
++Win32_Graphics_Direct3D12 = []
++Win32_Graphics_Direct3D9 = []
++Win32_Graphics_Direct3D9on12 = []
++Win32_Graphics_Direct3D_Dxc = []
++Win32_Graphics_Direct3D_Fxc = []
++Win32_Graphics_DirectComposition = []
++Win32_Graphics_DirectDraw = []
++Win32_Graphics_DirectManipulation = []
++Win32_Graphics_DirectWrite = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Dxgi = []
++Win32_Graphics_Dxgi_Common = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_Imaging = []
++Win32_Graphics_Imaging_D2D = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_Audio_Apo = []
++Win32_Media_Audio_DirectMusic = []
++Win32_Media_Audio_DirectSound = []
++Win32_Media_Audio_Endpoints = []
++Win32_Media_Audio_XAudio2 = []
++Win32_Media_DeviceManager = []
++Win32_Media_DirectShow = []
++Win32_Media_DirectShow_Tv = []
++Win32_Media_DirectShow_Xml = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_LibrarySharingServices = []
++Win32_Media_MediaFoundation = []
++Win32_Media_MediaPlayer = []
++Win32_Media_Multimedia = []
++Win32_Media_PictureAcquisition = []
++Win32_Media_Speech = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_MobileBroadband = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_NetworkPolicyServer = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectNow = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_BackgroundIntelligentTransferService = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_NetworkListManager = []
++Win32_Networking_RemoteDifferentialCompression = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authentication_Identity_Provider = []
++Win32_Security_Authorization = []
++Win32_Security_Authorization_UI = []
++Win32_Security_ConfigurationSnapin = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_Tpm = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DataDeduplication = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_EnhancedStorage = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileServerResourceManager = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_Packaging_Opc = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_VirtualDiskService = []
++Win32_Storage_Vss = []
++Win32_Storage_Xps = []
++Win32_Storage_Xps_Printing = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_AssessmentTool = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_CallObj = []
++Win32_System_Com_ChannelCredentials = []
++Win32_System_Com_Events = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_UI = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_Contacts = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DesktopSharing = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_ClrProfiling = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_ActiveScript = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Mmc = []
++Win32_System_Ole = []
++Win32_System_ParentalControls = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_RealTimeCommunications = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteAssistance = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_ServerBackup = []
++Win32_System_Services = []
++Win32_System_SettingsManagementInfrastructure = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_SideShow = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_TaskScheduler = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_TransactionServer = []
++Win32_System_UpdateAgent = []
++Win32_System_UpdateAssessment = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WinRT = []
++Win32_System_WinRT_AllJoyn = []
++Win32_System_WinRT_Composition = []
++Win32_System_WinRT_CoreInputView = []
++Win32_System_WinRT_Direct3D11 = []
++Win32_System_WinRT_Display = []
++Win32_System_WinRT_Graphics = []
++Win32_System_WinRT_Graphics_Capture = []
++Win32_System_WinRT_Graphics_Direct2D = []
++Win32_System_WinRT_Graphics_Imaging = []
++Win32_System_WinRT_Holographic = []
++Win32_System_WinRT_Isolation = []
++Win32_System_WinRT_ML = []
++Win32_System_WinRT_Media = []
++Win32_System_WinRT_Metadata = []
++Win32_System_WinRT_Pdf = []
++Win32_System_WinRT_Printing = []
++Win32_System_WinRT_Shell = []
++Win32_System_WinRT_Storage = []
++Win32_System_WindowsProgramming = []
++Win32_System_WindowsSync = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_Animation = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_Controls_RichEdit = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_Ink = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Radial = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_LegacyWindowsEnvironmentFeatures = []
++Win32_UI_Magnification = []
++Win32_UI_Notifications = []
++Win32_UI_Ribbon = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_UI_Wpf = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
+ default = []
+ deprecated = []
+ docs = []
+ implement = [
+-    "windows-implement",
+-    "windows-interface",
+-    "windows-core/implement",
+ ]
+ [lints.rust]
diff --git a/tests/configs/windows-0.58/debian/patches/series b/tests/configs/windows-0.58/debian/patches/series
new file mode 100644 (file)
index 0000000..20d1cc7
--- /dev/null
@@ -0,0 +1 @@
+remove-cycles.patch
diff --git a/tests/configs/windows-0.58/debian/rules b/tests/configs/windows-0.58/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-0.58/debian/rules.debcargo.hint b/tests/configs/windows-0.58/debian/rules.debcargo.hint
new file mode 100755 (executable)
index 0000000..92c239b
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+       dh_auto_test -- test --all
diff --git a/tests/configs/windows-i686-gnullvm-0.52/debian/debcargo.toml b/tests/configs/windows-i686-gnullvm-0.52/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-i686-gnullvm-0.52/debian/rules b/tests/configs/windows-i686-gnullvm-0.52/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/windows-sys-0.59/debian/changelog b/tests/configs/windows-sys-0.59/debian/changelog
new file mode 100644 (file)
index 0000000..bfc9255
--- /dev/null
@@ -0,0 +1,6 @@
+rust-windows-sys-0.59 (0.59.0-1) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package windows-sys 0.59.0 from crates.io using debcargo 2.6.1
+
+ -- Fabian Grünbichler <debian@fabian.gruenbichler.email>  Thu, 19 Sep 2024 17:15:57 +0200
diff --git a/tests/configs/windows-sys-0.59/debian/debcargo.toml b/tests/configs/windows-sys-0.59/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..59745d0
--- /dev/null
@@ -0,0 +1,6 @@
+overlay = "."
+
+[packages.lib]
+test_is_broken = false
+[packages."lib+Win32_Foundation"]
+test_is_broken = false
diff --git a/tests/configs/windows-sys-0.59/debian/patches/remove-cycles.patch b/tests/configs/windows-sys-0.59/debian/patches/remove-cycles.patch
new file mode 100644 (file)
index 0000000..80cedec
--- /dev/null
@@ -0,0 +1,491 @@
+Index: rust-windows-sys-0.59.0/Cargo.toml
+===================================================================
+--- rust-windows-sys-0.59.0.orig/Cargo.toml
++++ rust-windows-sys-0.59.0/Cargo.toml
+@@ -42,246 +42,246 @@ doctest = false
+ version = "0.52.6"
+ [features]
+-Wdk = ["Win32_Foundation"]
+-Wdk_Devices = ["Wdk"]
+-Wdk_Devices_Bluetooth = ["Wdk_Devices"]
+-Wdk_Devices_HumanInterfaceDevice = ["Wdk_Devices"]
+-Wdk_Foundation = ["Wdk"]
+-Wdk_Graphics = ["Wdk"]
+-Wdk_Graphics_Direct3D = ["Wdk_Graphics"]
+-Wdk_NetworkManagement = ["Wdk"]
+-Wdk_NetworkManagement_Ndis = ["Wdk_NetworkManagement"]
+-Wdk_NetworkManagement_WindowsFilteringPlatform = ["Wdk_NetworkManagement"]
+-Wdk_Storage = ["Wdk"]
+-Wdk_Storage_FileSystem = ["Wdk_Storage"]
+-Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"]
+-Wdk_System = ["Wdk"]
+-Wdk_System_IO = ["Wdk_System"]
+-Wdk_System_Memory = ["Wdk_System"]
+-Wdk_System_OfflineRegistry = ["Wdk_System"]
+-Wdk_System_Registry = ["Wdk_System"]
+-Wdk_System_SystemInformation = ["Wdk_System"]
+-Wdk_System_SystemServices = ["Wdk_System"]
+-Wdk_System_Threading = ["Wdk_System"]
+-Win32 = ["Win32_Foundation"]
+-Win32_Data = ["Win32"]
+-Win32_Data_HtmlHelp = ["Win32_Data"]
+-Win32_Data_RightsManagement = ["Win32_Data"]
+-Win32_Devices = ["Win32"]
+-Win32_Devices_AllJoyn = ["Win32_Devices"]
+-Win32_Devices_BiometricFramework = ["Win32_Devices"]
+-Win32_Devices_Bluetooth = ["Win32_Devices"]
+-Win32_Devices_Communication = ["Win32_Devices"]
+-Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"]
+-Win32_Devices_DeviceQuery = ["Win32_Devices"]
+-Win32_Devices_Display = ["Win32_Devices"]
+-Win32_Devices_Enumeration = ["Win32_Devices"]
+-Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"]
+-Win32_Devices_Fax = ["Win32_Devices"]
+-Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"]
+-Win32_Devices_PortableDevices = ["Win32_Devices"]
+-Win32_Devices_Properties = ["Win32_Devices"]
+-Win32_Devices_Pwm = ["Win32_Devices"]
+-Win32_Devices_Sensors = ["Win32_Devices"]
+-Win32_Devices_SerialCommunication = ["Win32_Devices"]
+-Win32_Devices_Tapi = ["Win32_Devices"]
+-Win32_Devices_Usb = ["Win32_Devices"]
+-Win32_Devices_WebServicesOnDevices = ["Win32_Devices"]
+-Win32_Foundation = ["Win32"]
+-Win32_Gaming = ["Win32"]
+-Win32_Globalization = ["Win32"]
+-Win32_Graphics = ["Win32"]
+-Win32_Graphics_Dwm = ["Win32_Graphics"]
+-Win32_Graphics_Gdi = ["Win32_Graphics"]
+-Win32_Graphics_GdiPlus = ["Win32_Graphics"]
+-Win32_Graphics_Hlsl = ["Win32_Graphics"]
+-Win32_Graphics_OpenGL = ["Win32_Graphics"]
+-Win32_Graphics_Printing = ["Win32_Graphics"]
+-Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"]
+-Win32_Management = ["Win32"]
+-Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"]
+-Win32_Media = ["Win32"]
+-Win32_Media_Audio = ["Win32_Media"]
+-Win32_Media_DxMediaObjects = ["Win32_Media"]
+-Win32_Media_KernelStreaming = ["Win32_Media"]
+-Win32_Media_Multimedia = ["Win32_Media"]
+-Win32_Media_Streaming = ["Win32_Media"]
+-Win32_Media_WindowsMediaFormat = ["Win32_Media"]
+-Win32_NetworkManagement = ["Win32"]
+-Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"]
+-Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"]
+-Win32_Networking = ["Win32"]
+-Win32_Networking_ActiveDirectory = ["Win32_Networking"]
+-Win32_Networking_Clustering = ["Win32_Networking"]
+-Win32_Networking_HttpServer = ["Win32_Networking"]
+-Win32_Networking_Ldap = ["Win32_Networking"]
+-Win32_Networking_WebSocket = ["Win32_Networking"]
+-Win32_Networking_WinHttp = ["Win32_Networking"]
+-Win32_Networking_WinInet = ["Win32_Networking"]
+-Win32_Networking_WinSock = ["Win32_Networking"]
+-Win32_Networking_WindowsWebServices = ["Win32_Networking"]
+-Win32_Security = ["Win32"]
+-Win32_Security_AppLocker = ["Win32_Security"]
+-Win32_Security_Authentication = ["Win32_Security"]
+-Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"]
+-Win32_Security_Authorization = ["Win32_Security"]
+-Win32_Security_Credentials = ["Win32_Security"]
+-Win32_Security_Cryptography = ["Win32_Security"]
+-Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"]
+-Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"]
+-Win32_Security_DiagnosticDataQuery = ["Win32_Security"]
+-Win32_Security_DirectoryServices = ["Win32_Security"]
+-Win32_Security_EnterpriseData = ["Win32_Security"]
+-Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"]
+-Win32_Security_Isolation = ["Win32_Security"]
+-Win32_Security_LicenseProtection = ["Win32_Security"]
+-Win32_Security_NetworkAccessProtection = ["Win32_Security"]
+-Win32_Security_WinTrust = ["Win32_Security"]
+-Win32_Security_WinWlx = ["Win32_Security"]
+-Win32_Storage = ["Win32"]
+-Win32_Storage_Cabinets = ["Win32_Storage"]
+-Win32_Storage_CloudFilters = ["Win32_Storage"]
+-Win32_Storage_Compression = ["Win32_Storage"]
+-Win32_Storage_DistributedFileSystem = ["Win32_Storage"]
+-Win32_Storage_FileHistory = ["Win32_Storage"]
+-Win32_Storage_FileSystem = ["Win32_Storage"]
+-Win32_Storage_Imapi = ["Win32_Storage"]
+-Win32_Storage_IndexServer = ["Win32_Storage"]
+-Win32_Storage_InstallableFileSystems = ["Win32_Storage"]
+-Win32_Storage_IscsiDisc = ["Win32_Storage"]
+-Win32_Storage_Jet = ["Win32_Storage"]
+-Win32_Storage_Nvme = ["Win32_Storage"]
+-Win32_Storage_OfflineFiles = ["Win32_Storage"]
+-Win32_Storage_OperationRecorder = ["Win32_Storage"]
+-Win32_Storage_Packaging = ["Win32_Storage"]
+-Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"]
+-Win32_Storage_ProjectedFileSystem = ["Win32_Storage"]
+-Win32_Storage_StructuredStorage = ["Win32_Storage"]
+-Win32_Storage_Vhd = ["Win32_Storage"]
+-Win32_Storage_Xps = ["Win32_Storage"]
+-Win32_System = ["Win32"]
+-Win32_System_AddressBook = ["Win32_System"]
+-Win32_System_Antimalware = ["Win32_System"]
+-Win32_System_ApplicationInstallationAndServicing = ["Win32_System"]
+-Win32_System_ApplicationVerifier = ["Win32_System"]
+-Win32_System_ClrHosting = ["Win32_System"]
+-Win32_System_Com = ["Win32_System"]
+-Win32_System_Com_Marshal = ["Win32_System_Com"]
+-Win32_System_Com_StructuredStorage = ["Win32_System_Com"]
+-Win32_System_Com_Urlmon = ["Win32_System_Com"]
+-Win32_System_ComponentServices = ["Win32_System"]
+-Win32_System_Console = ["Win32_System"]
+-Win32_System_CorrelationVector = ["Win32_System"]
+-Win32_System_DataExchange = ["Win32_System"]
+-Win32_System_DeploymentServices = ["Win32_System"]
+-Win32_System_DeveloperLicensing = ["Win32_System"]
+-Win32_System_Diagnostics = ["Win32_System"]
+-Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"]
+-Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"]
+-Win32_System_Diagnostics_TraceLogging = ["Win32_System_Diagnostics"]
+-Win32_System_DistributedTransactionCoordinator = ["Win32_System"]
+-Win32_System_Environment = ["Win32_System"]
+-Win32_System_ErrorReporting = ["Win32_System"]
+-Win32_System_EventCollector = ["Win32_System"]
+-Win32_System_EventLog = ["Win32_System"]
+-Win32_System_EventNotificationService = ["Win32_System"]
+-Win32_System_GroupPolicy = ["Win32_System"]
+-Win32_System_HostCompute = ["Win32_System"]
+-Win32_System_HostComputeNetwork = ["Win32_System"]
+-Win32_System_HostComputeSystem = ["Win32_System"]
+-Win32_System_Hypervisor = ["Win32_System"]
+-Win32_System_IO = ["Win32_System"]
+-Win32_System_Iis = ["Win32_System"]
+-Win32_System_Ioctl = ["Win32_System"]
+-Win32_System_JobObjects = ["Win32_System"]
+-Win32_System_Js = ["Win32_System"]
+-Win32_System_Kernel = ["Win32_System"]
+-Win32_System_LibraryLoader = ["Win32_System"]
+-Win32_System_Mailslots = ["Win32_System"]
+-Win32_System_Mapi = ["Win32_System"]
+-Win32_System_Memory = ["Win32_System"]
+-Win32_System_Memory_NonVolatile = ["Win32_System_Memory"]
+-Win32_System_MessageQueuing = ["Win32_System"]
+-Win32_System_MixedReality = ["Win32_System"]
+-Win32_System_Ole = ["Win32_System"]
+-Win32_System_PasswordManagement = ["Win32_System"]
+-Win32_System_Performance = ["Win32_System"]
+-Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"]
+-Win32_System_Pipes = ["Win32_System"]
+-Win32_System_Power = ["Win32_System"]
+-Win32_System_ProcessStatus = ["Win32_System"]
+-Win32_System_Recovery = ["Win32_System"]
+-Win32_System_Registry = ["Win32_System"]
+-Win32_System_RemoteDesktop = ["Win32_System"]
+-Win32_System_RemoteManagement = ["Win32_System"]
+-Win32_System_RestartManager = ["Win32_System"]
+-Win32_System_Restore = ["Win32_System"]
+-Win32_System_Rpc = ["Win32_System"]
+-Win32_System_Search = ["Win32_System"]
+-Win32_System_Search_Common = ["Win32_System_Search"]
+-Win32_System_SecurityCenter = ["Win32_System"]
+-Win32_System_Services = ["Win32_System"]
+-Win32_System_SetupAndMigration = ["Win32_System"]
+-Win32_System_Shutdown = ["Win32_System"]
+-Win32_System_StationsAndDesktops = ["Win32_System"]
+-Win32_System_SubsystemForLinux = ["Win32_System"]
+-Win32_System_SystemInformation = ["Win32_System"]
+-Win32_System_SystemServices = ["Win32_System"]
+-Win32_System_Threading = ["Win32_System"]
+-Win32_System_Time = ["Win32_System"]
+-Win32_System_TpmBaseServices = ["Win32_System"]
+-Win32_System_UserAccessLogging = ["Win32_System"]
+-Win32_System_Variant = ["Win32_System"]
+-Win32_System_VirtualDosMachines = ["Win32_System"]
+-Win32_System_WindowsProgramming = ["Win32_System"]
+-Win32_System_Wmi = ["Win32_System"]
+-Win32_UI = ["Win32"]
+-Win32_UI_Accessibility = ["Win32_UI"]
+-Win32_UI_ColorSystem = ["Win32_UI"]
+-Win32_UI_Controls = ["Win32_UI"]
+-Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"]
+-Win32_UI_HiDpi = ["Win32_UI"]
+-Win32_UI_Input = ["Win32_UI"]
+-Win32_UI_Input_Ime = ["Win32_UI_Input"]
+-Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"]
+-Win32_UI_Input_Pointer = ["Win32_UI_Input"]
+-Win32_UI_Input_Touch = ["Win32_UI_Input"]
+-Win32_UI_Input_XboxController = ["Win32_UI_Input"]
+-Win32_UI_InteractionContext = ["Win32_UI"]
+-Win32_UI_Magnification = ["Win32_UI"]
+-Win32_UI_Shell = ["Win32_UI"]
+-Win32_UI_Shell_Common = ["Win32_UI_Shell"]
+-Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"]
+-Win32_UI_TabletPC = ["Win32_UI"]
+-Win32_UI_TextServices = ["Win32_UI"]
+-Win32_UI_WindowsAndMessaging = ["Win32_UI"]
+-Win32_Web = ["Win32"]
+-Win32_Web_InternetExplorer = ["Win32_Web"]
++Wdk = []
++Wdk_Devices = []
++Wdk_Devices_Bluetooth = []
++Wdk_Devices_HumanInterfaceDevice = []
++Wdk_Foundation = []
++Wdk_Graphics = []
++Wdk_Graphics_Direct3D = []
++Wdk_NetworkManagement = []
++Wdk_NetworkManagement_Ndis = []
++Wdk_NetworkManagement_WindowsFilteringPlatform = []
++Wdk_Storage = []
++Wdk_Storage_FileSystem = []
++Wdk_Storage_FileSystem_Minifilters = []
++Wdk_System = []
++Wdk_System_IO = []
++Wdk_System_Memory = []
++Wdk_System_OfflineRegistry = []
++Wdk_System_Registry = []
++Wdk_System_SystemInformation = []
++Wdk_System_SystemServices = []
++Wdk_System_Threading = []
++Win32 = []
++Win32_Data = []
++Win32_Data_HtmlHelp = []
++Win32_Data_RightsManagement = []
++Win32_Devices = []
++Win32_Devices_AllJoyn = []
++Win32_Devices_BiometricFramework = []
++Win32_Devices_Bluetooth = []
++Win32_Devices_Communication = []
++Win32_Devices_DeviceAndDriverInstallation = []
++Win32_Devices_DeviceQuery = []
++Win32_Devices_Display = []
++Win32_Devices_Enumeration = []
++Win32_Devices_Enumeration_Pnp = []
++Win32_Devices_Fax = []
++Win32_Devices_HumanInterfaceDevice = []
++Win32_Devices_PortableDevices = []
++Win32_Devices_Properties = []
++Win32_Devices_Pwm = []
++Win32_Devices_Sensors = []
++Win32_Devices_SerialCommunication = []
++Win32_Devices_Tapi = []
++Win32_Devices_Usb = []
++Win32_Devices_WebServicesOnDevices = []
++Win32_Foundation = []
++Win32_Gaming = []
++Win32_Globalization = []
++Win32_Graphics = []
++Win32_Graphics_Dwm = []
++Win32_Graphics_Gdi = []
++Win32_Graphics_GdiPlus = []
++Win32_Graphics_Hlsl = []
++Win32_Graphics_OpenGL = []
++Win32_Graphics_Printing = []
++Win32_Graphics_Printing_PrintTicket = []
++Win32_Management = []
++Win32_Management_MobileDeviceManagementRegistration = []
++Win32_Media = []
++Win32_Media_Audio = []
++Win32_Media_DxMediaObjects = []
++Win32_Media_KernelStreaming = []
++Win32_Media_Multimedia = []
++Win32_Media_Streaming = []
++Win32_Media_WindowsMediaFormat = []
++Win32_NetworkManagement = []
++Win32_NetworkManagement_Dhcp = []
++Win32_NetworkManagement_Dns = []
++Win32_NetworkManagement_InternetConnectionWizard = []
++Win32_NetworkManagement_IpHelper = []
++Win32_NetworkManagement_Multicast = []
++Win32_NetworkManagement_Ndis = []
++Win32_NetworkManagement_NetBios = []
++Win32_NetworkManagement_NetManagement = []
++Win32_NetworkManagement_NetShell = []
++Win32_NetworkManagement_NetworkDiagnosticsFramework = []
++Win32_NetworkManagement_P2P = []
++Win32_NetworkManagement_QoS = []
++Win32_NetworkManagement_Rras = []
++Win32_NetworkManagement_Snmp = []
++Win32_NetworkManagement_WNet = []
++Win32_NetworkManagement_WebDav = []
++Win32_NetworkManagement_WiFi = []
++Win32_NetworkManagement_WindowsConnectionManager = []
++Win32_NetworkManagement_WindowsFilteringPlatform = []
++Win32_NetworkManagement_WindowsFirewall = []
++Win32_NetworkManagement_WindowsNetworkVirtualization = []
++Win32_Networking = []
++Win32_Networking_ActiveDirectory = []
++Win32_Networking_Clustering = []
++Win32_Networking_HttpServer = []
++Win32_Networking_Ldap = []
++Win32_Networking_WebSocket = []
++Win32_Networking_WinHttp = []
++Win32_Networking_WinInet = []
++Win32_Networking_WinSock = []
++Win32_Networking_WindowsWebServices = []
++Win32_Security = []
++Win32_Security_AppLocker = []
++Win32_Security_Authentication = []
++Win32_Security_Authentication_Identity = []
++Win32_Security_Authorization = []
++Win32_Security_Credentials = []
++Win32_Security_Cryptography = []
++Win32_Security_Cryptography_Catalog = []
++Win32_Security_Cryptography_Certificates = []
++Win32_Security_Cryptography_Sip = []
++Win32_Security_Cryptography_UI = []
++Win32_Security_DiagnosticDataQuery = []
++Win32_Security_DirectoryServices = []
++Win32_Security_EnterpriseData = []
++Win32_Security_ExtensibleAuthenticationProtocol = []
++Win32_Security_Isolation = []
++Win32_Security_LicenseProtection = []
++Win32_Security_NetworkAccessProtection = []
++Win32_Security_WinTrust = []
++Win32_Security_WinWlx = []
++Win32_Storage = []
++Win32_Storage_Cabinets = []
++Win32_Storage_CloudFilters = []
++Win32_Storage_Compression = []
++Win32_Storage_DistributedFileSystem = []
++Win32_Storage_FileHistory = []
++Win32_Storage_FileSystem = []
++Win32_Storage_Imapi = []
++Win32_Storage_IndexServer = []
++Win32_Storage_InstallableFileSystems = []
++Win32_Storage_IscsiDisc = []
++Win32_Storage_Jet = []
++Win32_Storage_Nvme = []
++Win32_Storage_OfflineFiles = []
++Win32_Storage_OperationRecorder = []
++Win32_Storage_Packaging = []
++Win32_Storage_Packaging_Appx = []
++Win32_Storage_ProjectedFileSystem = []
++Win32_Storage_StructuredStorage = []
++Win32_Storage_Vhd = []
++Win32_Storage_Xps = []
++Win32_System = []
++Win32_System_AddressBook = []
++Win32_System_Antimalware = []
++Win32_System_ApplicationInstallationAndServicing = []
++Win32_System_ApplicationVerifier = []
++Win32_System_ClrHosting = []
++Win32_System_Com = []
++Win32_System_Com_Marshal = []
++Win32_System_Com_StructuredStorage = []
++Win32_System_Com_Urlmon = []
++Win32_System_ComponentServices = []
++Win32_System_Console = []
++Win32_System_CorrelationVector = []
++Win32_System_DataExchange = []
++Win32_System_DeploymentServices = []
++Win32_System_DeveloperLicensing = []
++Win32_System_Diagnostics = []
++Win32_System_Diagnostics_Ceip = []
++Win32_System_Diagnostics_Debug = []
++Win32_System_Diagnostics_Debug_Extensions = []
++Win32_System_Diagnostics_Etw = []
++Win32_System_Diagnostics_ProcessSnapshotting = []
++Win32_System_Diagnostics_ToolHelp = []
++Win32_System_Diagnostics_TraceLogging = []
++Win32_System_DistributedTransactionCoordinator = []
++Win32_System_Environment = []
++Win32_System_ErrorReporting = []
++Win32_System_EventCollector = []
++Win32_System_EventLog = []
++Win32_System_EventNotificationService = []
++Win32_System_GroupPolicy = []
++Win32_System_HostCompute = []
++Win32_System_HostComputeNetwork = []
++Win32_System_HostComputeSystem = []
++Win32_System_Hypervisor = []
++Win32_System_IO = []
++Win32_System_Iis = []
++Win32_System_Ioctl = []
++Win32_System_JobObjects = []
++Win32_System_Js = []
++Win32_System_Kernel = []
++Win32_System_LibraryLoader = []
++Win32_System_Mailslots = []
++Win32_System_Mapi = []
++Win32_System_Memory = []
++Win32_System_Memory_NonVolatile = []
++Win32_System_MessageQueuing = []
++Win32_System_MixedReality = []
++Win32_System_Ole = []
++Win32_System_PasswordManagement = []
++Win32_System_Performance = []
++Win32_System_Performance_HardwareCounterProfiling = []
++Win32_System_Pipes = []
++Win32_System_Power = []
++Win32_System_ProcessStatus = []
++Win32_System_Recovery = []
++Win32_System_Registry = []
++Win32_System_RemoteDesktop = []
++Win32_System_RemoteManagement = []
++Win32_System_RestartManager = []
++Win32_System_Restore = []
++Win32_System_Rpc = []
++Win32_System_Search = []
++Win32_System_Search_Common = []
++Win32_System_SecurityCenter = []
++Win32_System_Services = []
++Win32_System_SetupAndMigration = []
++Win32_System_Shutdown = []
++Win32_System_StationsAndDesktops = []
++Win32_System_SubsystemForLinux = []
++Win32_System_SystemInformation = []
++Win32_System_SystemServices = []
++Win32_System_Threading = []
++Win32_System_Time = []
++Win32_System_TpmBaseServices = []
++Win32_System_UserAccessLogging = []
++Win32_System_Variant = []
++Win32_System_VirtualDosMachines = []
++Win32_System_WindowsProgramming = []
++Win32_System_Wmi = []
++Win32_UI = []
++Win32_UI_Accessibility = []
++Win32_UI_ColorSystem = []
++Win32_UI_Controls = []
++Win32_UI_Controls_Dialogs = []
++Win32_UI_HiDpi = []
++Win32_UI_Input = []
++Win32_UI_Input_Ime = []
++Win32_UI_Input_KeyboardAndMouse = []
++Win32_UI_Input_Pointer = []
++Win32_UI_Input_Touch = []
++Win32_UI_Input_XboxController = []
++Win32_UI_InteractionContext = []
++Win32_UI_Magnification = []
++Win32_UI_Shell = []
++Win32_UI_Shell_Common = []
++Win32_UI_Shell_PropertiesSystem = []
++Win32_UI_TabletPC = []
++Win32_UI_TextServices = []
++Win32_UI_WindowsAndMessaging = []
++Win32_Web = []
++Win32_Web_InternetExplorer = []
+ default = []
+ docs = []
diff --git a/tests/configs/windows-sys-0.59/debian/patches/series b/tests/configs/windows-sys-0.59/debian/patches/series
new file mode 100644 (file)
index 0000000..20d1cc7
--- /dev/null
@@ -0,0 +1 @@
+remove-cycles.patch
diff --git a/tests/configs/windows-sys-0.59/debian/rules b/tests/configs/windows-sys-0.59/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/windows-sys-0.59/debian/rules.debcargo.hint b/tests/configs/windows-sys-0.59/debian/rules.debcargo.hint
new file mode 100755 (executable)
index 0000000..92c239b
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+
+override_dh_auto_test:
+       dh_auto_test -- test --all
diff --git a/tests/configs/windows-x86-64-gnullvm-0.42/debian/debcargo.toml b/tests/configs/windows-x86-64-gnullvm-0.42/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-x86-64-gnullvm-0.42/debian/rules b/tests/configs/windows-x86-64-gnullvm-0.42/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/windows-x86-64-gnullvm-0.48/debian/debcargo.toml b/tests/configs/windows-x86-64-gnullvm-0.48/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-x86-64-gnullvm-0.48/debian/rules b/tests/configs/windows-x86-64-gnullvm-0.48/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/windows-x86-64-gnullvm-0.52/debian/debcargo.toml b/tests/configs/windows-x86-64-gnullvm-0.52/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/windows-x86-64-gnullvm-0.52/debian/rules b/tests/configs/windows-x86-64-gnullvm-0.52/debian/rules
new file mode 100755 (executable)
index 0000000..6c28854
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+%:
+       dh $@ --buildsystem cargo
+export RUSTC_BOOTSTRAP := 1
+export PATH := $(CURDIR)/debian/debcargo_testing_bin:$(PATH)
+
+override_dh_strip:
diff --git a/tests/configs/winreg-0.10/debian/debcargo.toml b/tests/configs/winreg-0.10/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/winreg-0.10/debian/rules b/tests/configs/winreg-0.10/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/winreg-0.50/debian/debcargo.toml b/tests/configs/winreg-0.50/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/winreg-0.50/debian/rules b/tests/configs/winreg-0.50/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/winreg-0.6/debian/debcargo.toml b/tests/configs/winreg-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/winreg-0.6/debian/rules b/tests/configs/winreg-0.6/debian/rules
new file mode 100644 (file)
index 0000000..b92cbbc
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# only supported on windows
+override_dh_auto_test:
+       case $(DEB_HOST_RUST_TYPE) in *-pc-windows-gnu) dh_auto_test;; *) true;; esac
diff --git a/tests/configs/x86-0.33/debian/debcargo.toml b/tests/configs/x86-0.33/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..94ffe4a
--- /dev/null
@@ -0,0 +1,2 @@
+semver_suffix = true
+overlay = "."
diff --git a/tests/configs/x86-0.33/debian/rules b/tests/configs/x86-0.33/debian/rules
new file mode 100644 (file)
index 0000000..bfcc84f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+include /usr/share/rustc/architecture.mk
+%:
+       dh $@ --buildsystem cargo
+
+# code uses old rust feature that causes compiler error.
+override_dh_auto_test:
+       dh_auto_test || true
+
+# This crate is actually broken; however there are several cases why this
+# override is OK and necessary for Debian:
+#
+# 1. The other crate depends on this broken crate in an architecture-specific
+#    way i.e. with [target.$arch.*] in Cargo.toml
+#
+#    cargo does not yet support omitting these dependencies on other arches [1]
+#    and so we are forced to include it also in debcargo [2]
+#
+#    [1] https://github.com/rust-lang/cargo/issues/5896
+#    [2] https://salsa.debian.org/rust-team/debcargo/-/issues/14
+#
+# 2. The other crate depends on this broken crate only via one of its optional
+#    features that most users of that crate, don't need. You generally run into
+#    this situation when resolving via --resolve-type BinaryAllForDebianTesting
+#
+# If your situation does not fit into one of the above situations, you should
+# re-consider the override. If your override is incorrect, the build failure
+# will crop up again later, in the crate that depends on this broken crate.
diff --git a/tests/configs/yeslogic-fontconfig-sys-6/debian/debcargo.toml b/tests/configs/yeslogic-fontconfig-sys-6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..6f7b4cf
--- /dev/null
@@ -0,0 +1,5 @@
+overlay = "."
+semver_suffix = true
+
+[packages.lib]
+depends = ["libfontconfig-dev"]
diff --git a/tests/configs/zip-0.5/debian/debcargo.toml b/tests/configs/zip-0.5/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..66c76f8
--- /dev/null
@@ -0,0 +1,3 @@
+semver_suffix = true
+# tests purposefully contain invalid data that debian tools try to process
+excludes = ["tests/**"]
diff --git a/tests/configs/zip-0.6/debian/debcargo.toml b/tests/configs/zip-0.6/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..66c76f8
--- /dev/null
@@ -0,0 +1,3 @@
+semver_suffix = true
+# tests purposefully contain invalid data that debian tools try to process
+excludes = ["tests/**"]
diff --git a/tests/configs/zip/debian/debcargo.toml b/tests/configs/zip/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..66c76f8
--- /dev/null
@@ -0,0 +1,3 @@
+semver_suffix = true
+# tests purposefully contain invalid data that debian tools try to process
+excludes = ["tests/**"]
diff --git a/tests/debcargo_override.toml b/tests/debcargo_override.toml
new file mode 100644 (file)
index 0000000..2141748
--- /dev/null
@@ -0,0 +1,14 @@
+uploaders = ["Sylvestre Ledru <sylvestre@debian.org>", "Ximin Luo <infinity0@debian.org>" ]
+
+[source]
+section = "rust"
+build_depends = ["libssl-dev"]
+homepage = "https://salsa.debian.org/rust-team/debcargo-conf"
+
+[packages.bin]
+summary = "Tool to create Debian package from Rust crate"
+description = """
+This package provides debcargo a tool to create Debian source package from Rust
+crate. The package created by this tool is as per the packaging policy set by
+Debian Rust team.
+"""
diff --git a/tests/debcargo_override_top_level.toml b/tests/debcargo_override_top_level.toml
new file mode 100644 (file)
index 0000000..13d0d95
--- /dev/null
@@ -0,0 +1,13 @@
+uploaders = ["Sylvestre Ledru <sylvestre@debian.org>", "Ximin Luo <infinity0@debian.org>" ]
+
+summary = "Tool to create Debian package from Rust crate"
+description = """
+This package provides debcargo a tool to create Debian source package from Rust
+crate. The package created by this tool is as per the packaging policy set by
+Debian Rust team.
+"""
+
+[source]
+section = "rust"
+build_depends = ["libssl-dev"]
+homepage = "https://salsa.debian.org/rust-team/debcargo-conf"
diff --git a/tests/foobar-overlay/debian/debcargo.toml b/tests/foobar-overlay/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..9b982f8
--- /dev/null
@@ -0,0 +1,14 @@
+overlay = "."
+crate_src_path = "../../foobar"
+
+[source]
+build_depends = ["some-build-dependency"]
+
+[packages.lib]
+depends = ["some-dependency-for-lib"]
+conflicts = ["global-conflict"]
+
+[packages."lib+somefeature"]
+depends = ["some-dependency-for-lib-with-feature"]
+breaks = ["broken-by-somefeature"]
+replaces = ["replaced-by-somefeature"]
diff --git a/tests/foobar-semver-overlay/debian/debcargo.toml b/tests/foobar-semver-overlay/debian/debcargo.toml
new file mode 100644 (file)
index 0000000..f3d8499
--- /dev/null
@@ -0,0 +1,19 @@
+overlay = "."
+crate_src_path = "../../foobar-semver"
+semver_suffix = true
+requires_root = "no"
+
+[source]
+build_depends = ["some-build-dependency"]
+skip_nocheck = true
+
+[packages.lib]
+depends = ["some-dependency-for-lib"]
+breaks = ["broken-by-everything"]
+replaces = ["replaced-by-everything"]
+conflicts = ["global-conflict"]
+
+[packages."lib+somefeature"]
+depends = ["some-dependency-for-lib-with-feature"]
+breaks = ["broken-by-somefeature"]
+replaces = ["replaced-by-somefeature"]
diff --git a/tests/foobar-semver.expected b/tests/foobar-semver.expected
new file mode 100644 (file)
index 0000000..abcdbf9
--- /dev/null
@@ -0,0 +1,94 @@
+Source: rust-foobar-semver-0.1
+Section: rust
+Priority: optional
+Build-Depends: debhelper-compat (= 13),
+ dh-sequence-cargo,
+ some-build-dependency
+Build-Depends-Arch: cargo:native,
+ rustc:native,
+ libstd-rust-dev,
+ librust-anyhow-1+default-dev (>= 1.0.96-~~),
+ some-dependency-for-lib
+Maintainer: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+Standards-Version: 4.7.2
+Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/foobar-semver-0.1]
+Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/foobar-semver-0.1
+X-Cargo-Crate: foobar-semver
+Rules-Requires-Root: no
+
+Package: librust-foobar-semver-0.1-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-anyhow-1+default-dev (>= 1.0.96-~~),
+ some-dependency-for-lib
+Suggests:
+ librust-foobar-semver-0.1+futures-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+somefeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+someotherfeature-dev (= ${binary:Version})
+Provides:
+ librust-foobar-semver-0-dev (= ${binary:Version}),
+ librust-foobar-semver-0+default-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+default-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+default-dev (= ${binary:Version})
+Replaces:
+ librust-foobar-semver-dev (<< 0.1.1~),
+ replaced-by-everything
+Breaks:
+ librust-foobar-semver-dev (<< 0.1.1~),
+ broken-by-everything
+Conflicts:
+ global-conflict
+Description: Rust crate "foobar-semver" - Rust source code
+ Source code for Debianized Rust crate "foobar-semver"
+
+Package: librust-foobar-semver-0.1+futures-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-semver-0.1-dev (= ${binary:Version}),
+ librust-futures+default-dev (<< 0.4-~~),
+ librust-futures+default-dev (>= 0.2-~~)
+Provides:
+ librust-foobar-semver-0+futures-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+futures-dev (= ${binary:Version})
+Description: Rust crate "foobar-semver" - feature "futures"
+ This metapackage enables feature "futures" for the Rust foobar-semver crate, by
+ pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar-semver-0.1+somefeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-semver-0.1-dev (= ${binary:Version}),
+ librust-thiserror-2-dev,
+ some-dependency-for-lib-with-feature
+Provides:
+ librust-foobar-semver-0+somefeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+somefeature-dev (= ${binary:Version})
+Replaces:
+ replaced-by-somefeature
+Breaks:
+ broken-by-somefeature
+Description: Rust crate "foobar-semver" - feature "somefeature"
+ This metapackage enables feature "somefeature" for the Rust foobar-semver
+ crate, by pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar-semver-0.1+someotherfeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-semver-0.1-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+somefeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1+futures-dev (= ${binary:Version})
+Provides:
+ librust-foobar-semver-0+someotherfeature-dev (= ${binary:Version}),
+ librust-foobar-semver-0.1.0+someotherfeature-dev (= ${binary:Version})
+Description: Rust crate "foobar-semver" - feature "someotherfeature"
+ This metapackage enables feature "someotherfeature" for the Rust foobar-semver
+ crate, by pulling in any additional dependencies needed by that feature.
diff --git a/tests/foobar.expected b/tests/foobar.expected
new file mode 100644 (file)
index 0000000..c406efa
--- /dev/null
@@ -0,0 +1,92 @@
+Source: rust-foobar
+Section: rust
+Priority: optional
+Build-Depends: debhelper-compat (= 13),
+ dh-sequence-cargo,
+ some-build-dependency
+Build-Depends-Arch: cargo:native <!nocheck>,
+ rustc:native <!nocheck>,
+ libstd-rust-dev <!nocheck>,
+ librust-anyhow-1+default-dev (>= 1.0.96-~~) <!nocheck>,
+ some-dependency-for-lib <!nocheck>
+Maintainer: Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+Standards-Version: 4.7.2
+Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/foobar]
+Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/foobar
+X-Cargo-Crate: foobar
+
+Package: librust-foobar-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-anyhow-1+default-dev (>= 1.0.96-~~),
+ some-dependency-for-lib
+Suggests:
+ librust-foobar+futures-dev (= ${binary:Version}),
+ librust-foobar+somefeature-dev (= ${binary:Version}),
+ librust-foobar+someotherfeature-dev (= ${binary:Version})
+Provides:
+ librust-foobar+default-dev (= ${binary:Version}),
+ librust-foobar-0-dev (= ${binary:Version}),
+ librust-foobar-0+default-dev (= ${binary:Version}),
+ librust-foobar-0.1-dev (= ${binary:Version}),
+ librust-foobar-0.1+default-dev (= ${binary:Version}),
+ librust-foobar-0.1.0-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+default-dev (= ${binary:Version})
+Conflicts:
+ global-conflict
+Description: Rust crate "foobar" - Rust source code
+ Source code for Debianized Rust crate "foobar"
+
+Package: librust-foobar+futures-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-dev (= ${binary:Version}),
+ librust-futures+default-dev (<< 0.4-~~),
+ librust-futures+default-dev (>= 0.2-~~)
+Provides:
+ librust-foobar-0+futures-dev (= ${binary:Version}),
+ librust-foobar-0.1+futures-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+futures-dev (= ${binary:Version})
+Description: Rust crate "foobar" - feature "futures"
+ This metapackage enables feature "futures" for the Rust foobar crate, by
+ pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar+somefeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-dev (= ${binary:Version}),
+ librust-thiserror-2-dev,
+ some-dependency-for-lib-with-feature
+Provides:
+ librust-foobar-0+somefeature-dev (= ${binary:Version}),
+ librust-foobar-0.1+somefeature-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+somefeature-dev (= ${binary:Version})
+Replaces:
+ replaced-by-somefeature
+Breaks:
+ broken-by-somefeature
+Description: Rust crate "foobar" - feature "somefeature"
+ This metapackage enables feature "somefeature" for the Rust foobar crate, by
+ pulling in any additional dependencies needed by that feature.
+
+Package: librust-foobar+someotherfeature-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-foobar-dev (= ${binary:Version}),
+ librust-foobar+somefeature-dev (= ${binary:Version}),
+ librust-foobar+futures-dev (= ${binary:Version})
+Provides:
+ librust-foobar-0+someotherfeature-dev (= ${binary:Version}),
+ librust-foobar-0.1+someotherfeature-dev (= ${binary:Version}),
+ librust-foobar-0.1.0+someotherfeature-dev (= ${binary:Version})
+Description: Rust crate "foobar" - feature "someotherfeature"
+ This metapackage enables feature "someotherfeature" for the Rust foobar crate,
+ by pulling in any additional dependencies needed by that feature.
diff --git a/tests/local-crate.rs b/tests/local-crate.rs
new file mode 100644 (file)
index 0000000..ae24cc7
--- /dev/null
@@ -0,0 +1,59 @@
+extern crate debcargo;
+
+use std::path::{Path, PathBuf};
+
+fn local_package_test(tmpdir: &Path, crate_name: &str, version: &str) -> Option<String> {
+    let tempdir = tempfile::Builder::new()
+        .prefix("debcargo")
+        .tempdir_in(tmpdir)
+        .expect("Should be able to create temporary directory");
+    let manifest_dir = env!("CARGO_MANIFEST_DIR");
+    let crate_dir = PathBuf::from(manifest_dir).join("tests").join(crate_name);
+    if !crate_dir.exists() {
+        return None;
+    }
+    let output = std::process::Command::new(env!("CARGO_BIN_EXE_debcargo"))
+        .env("DEBFULLNAME", "Debcargo Test")
+        .env("DEBEMAIL", "debcargo@example.com")
+        .arg("package")
+        .arg("--config")
+        .arg(format!(
+            "{manifest_dir}/tests/{crate_name}-overlay/debian/debcargo.toml"
+        ))
+        .arg("--directory")
+        .arg(tempdir.path().join("output"))
+        .arg("--no-overlay-write-back")
+        .arg(crate_name)
+        .arg(version)
+        .output()
+        .expect("Should be able to run `debcargo package`");
+
+    assert!(output.status.success());
+
+    Some(
+        std::fs::read_to_string(tempdir.path().join("output/debian/control"))
+            .expect("Should be able to read generated debian/control file"),
+    )
+}
+
+#[test]
+fn generate_package_with_crate_src() {
+    let out_dir = PathBuf::from(env!("CARGO_TARGET_TMPDIR"));
+    if let Some(actual) = local_package_test(&out_dir, "foobar", "0.1.0") {
+        std::fs::write(out_dir.join("foobar.actual"), &actual)
+            .expect("Should be able to write out generate control contents");
+        let expected = include_str!("foobar.expected");
+        assert_eq!(actual, expected);
+    }
+}
+
+#[test]
+fn generate_package_with_semver_crate_src() {
+    let out_dir = PathBuf::from(env!("CARGO_TARGET_TMPDIR"));
+    if let Some(actual) = local_package_test(&out_dir, "foobar-semver", "0.1.0") {
+        std::fs::write(out_dir.join("foobar-semver.actual"), &actual)
+            .expect("Should be able to write out generate control contents");
+        let expected = include_str!("foobar-semver.expected");
+        assert_eq!(actual, expected);
+    }
+}
diff --git a/tests/manpages.rs b/tests/manpages.rs
new file mode 100644 (file)
index 0000000..54bc9d5
--- /dev/null
@@ -0,0 +1,67 @@
+use clap::CommandFactory;
+use clap_mangen::generate_to;
+use std::{fs, path::PathBuf};
+
+use debcargo::cli::Cli;
+
+#[test]
+fn check_manpages() {
+    let outdir = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join("manpages");
+    let manpages_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("manpages");
+
+    fs::remove_dir_all(&outdir).ok();
+    fs::create_dir_all(&outdir)
+        .unwrap_or_else(|e| panic!("Could not create temporary manpages directory: {e}"));
+
+    // Generate manpages from scratch
+    generate_to(Cli::command().flatten_help(true), &outdir)
+        .unwrap_or_else(|e| panic!("Could not generate temporary manpages: {e}"));
+
+    // For each generated manpage, check that it exists with the same content in the source directory
+    let changed_manpages: Vec<String> = fs::read_dir(&outdir)
+        .unwrap_or_else(|e| panic!("Could not read temporary manpages directory: {e}"))
+        .filter(|manpage| {
+            let new_manpage = manpage.as_ref().unwrap().path();
+            let old_manpage = manpages_dir.join(new_manpage.file_name().unwrap());
+            if !old_manpage.exists() {
+                true
+            } else {
+                let old_manpage_content = fs::read_to_string(&old_manpage).unwrap_or_else(|e| {
+                    panic!("Could not read {}: {e}", old_manpage.to_string_lossy())
+                });
+                let new_manpage_content = fs::read_to_string(&new_manpage).unwrap_or_else(|e| {
+                    panic!("Could not read {}: {e}", new_manpage.to_string_lossy())
+                });
+                old_manpage_content != new_manpage_content
+            }
+        })
+        .map(|manpage| manpage.unwrap().file_name().to_string_lossy().to_string())
+        .collect();
+
+    // For each manpage in the source directory, check that the generated one exists (i.e. whether
+    // it should be removed)
+    let removed_manpages: Vec<String> = fs::read_dir(&manpages_dir)
+        .unwrap()
+        .filter(|manpage| {
+            !outdir
+                .join(manpage.as_ref().unwrap().path().file_name().unwrap())
+                .exists()
+        })
+        .map(|manpage| manpage.unwrap().file_name().to_string_lossy().to_string())
+        .collect();
+
+    if !(changed_manpages.is_empty() && removed_manpages.is_empty()) {
+        let mut panic_string = vec![String::from("Manpages have changed!")];
+        if !changed_manpages.is_empty() {
+            panic_string.push(format!(
+                "- Please replace {} (new manpages generated in {})",
+                changed_manpages.join(", "),
+                outdir.to_string_lossy()
+            ));
+        }
+        if !removed_manpages.is_empty() {
+            panic_string.push(format!("- Please delete {}", removed_manpages.join(", "),));
+        }
+        panic!("{}", panic_string.join("\n"));
+    }
+}
diff --git a/tests/sh/integrate.sh b/tests/sh/integrate.sh
new file mode 100755 (executable)
index 0000000..0857022
--- /dev/null
@@ -0,0 +1,288 @@
+#!/bin/bash
+set -e
+
+scriptdir="$(dirname "$0")"
+
+# outputs
+directory=tmp
+failures_file=""
+# inputs
+allow_failures="$scriptdir/build-allow-fail"
+lintian_suppress_tags="$scriptdir/lintian-suppress-tags"
+config_dir="$scriptdir/../configs"
+# tweaks
+run_lintian=true
+run_sbuild=false
+keepfiles=false
+resolve=
+extraargs=
+
+export DEBCARGO_TESTING_IGNORE_DEBIAN_POLICY_VIOLATION=1
+export DEBCARGO_TESTING_RUZT=1
+
+export DEB_HOST_ARCH=${DEB_HOST_ARCH:-$(dpkg-architecture -qDEB_HOST_ARCH)}
+
+while getopts 'd:f:a:l:c:bkrRux:zh?' o; do
+       case $o in
+       d ) directory=$OPTARG;;
+       f ) failures_file=$OPTARG;;
+
+       a ) allow_failures=$OPTARG;;
+       c ) config_dir=$OPTARG;;
+
+       b ) run_sbuild=true;;
+       k ) keepfiles=true;;
+       r ) resolve=SourceForDebianUnstable;;
+       R ) resolve=BinaryAllForDebianTesting;;
+       x ) extraargs="$extraargs $OPTARG";;
+       h|\? ) cat >&2 <<eof
+Usage: $0 [-ru] (<crate name>|<path/to/crate>) [..]
+
+Run debcargo, do a source-only build, and call lintian on the results.
+
+  -h            This help text.
+
+Options for output:
+  -d DIR        Output directory, default: $directory. Warning: this will be
+                wiped at the start of the test!
+  -f FILE       File to output failed crates in, instead of exiting non-zero.
+                Relative paths are taken relative to the output directory.
+
+Options for input:
+  -a FILE       File that lists crate names to ignore failures for, default:
+                $allow_failures.
+  -c DIR        Path to config directory, default: $config_dir.
+
+Options to control running:
+  -b            Run sbuild on the resulting dsc package.
+  -k            Don't wipe the output directory at the start of the test, and
+                don't rebuild a crate if its directory already exists.
+  -r            Operate on all transitive build-dependencies of the source
+                package, needed for entry into Debian Unstable.
+  -R            Operate on all transitive dependencies of the binary packages,
+                needed for entry into Debian Testing.
+  -x ARG        Give ARG as an extra argument to debcargo, e.g. like
+                -x--copyright-guess-harder.
+eof
+               exit 2;;
+       esac
+done
+shift $(expr $OPTIND - 1)
+
+allow_fail() {
+       local crate="$1"
+       local version="$2"
+       if ! test -f "${allow_failures}"; then
+               return 1
+       elif grep -qx "${crate}" "${allow_failures}"; then
+               echo >&2 "Allowing ${crate} to fail..."
+               return 0
+       elif [ -n "$version" ] && grep -qx "${crate}-${version}" "${allow_failures}"; then
+               echo >&2 "Allowing ${crate}-${version} to fail..."
+               return 0
+       else
+               return 1
+       fi
+}
+
+shouldbuild() {
+       local dst="$1"
+       local src="$2"
+       test ! -e "$dst" -o "$src" -nt "$dst"
+}
+
+changelog_pkgname() {(
+       local cratedir="$1"
+       cd "$cratedir"
+       # dpkg-parsechangelog is really slow when dealing with hundreds of crates
+       #echo $(dpkg-parsechangelog -SSource)_$(dpkg-parsechangelog -SVersion)
+       head -n1 debian/changelog | sed -nre 's/^(\S*) \((\S*)\).*/\1_\2/gp'
+)}
+
+run_lintian() {(
+       local crate="$1"
+       local version="$2"
+       local cratedir="$crate${version:+-$version}"
+       cd "$directory"
+
+       allow_fail "$crate" $version && return 0
+
+       local base="$(changelog_pkgname "$cratedir")"
+       local out="${base}.lintian.out"
+
+       if ! ( shouldbuild "$out" "${base}_source.changes" \
+           || shouldbuild "$out" "${base}_${DEB_HOST_ARCH}.changes" ); then
+               echo >&2 "skipping already-linted ${base}_*.changes in ${out}"
+               return 0
+       fi
+
+       echo >&2 "running lintian for ${base} into ${out}"
+       rm -f "$out" "${out}.tmp"
+       changes="${base}_source.changes"
+       lintian --suppress-tags-from-file "$lintian_suppress_tags" -EIL +pedantic "$changes" | tee -a "${out}.tmp"
+       changes="${base}_${DEB_HOST_ARCH}.changes"
+       lintian --suppress-tags-from-file "$lintian_suppress_tags" -EIL +pedantic "$changes" | tee -a "${out}.tmp"
+       mv "${out}.tmp" "$out"
+)}
+
+if [ -z "$CHROOT" ]; then
+       if schroot -i -c "debcargo-unstable-${DEB_HOST_ARCH}-sbuild" >/dev/null 2>&1; then
+               CHROOT="debcargo-unstable-${DEB_HOST_ARCH}-sbuild"
+       else
+               CHROOT=${CHROOT:-unstable-"$DEB_HOST_ARCH"-sbuild}
+       fi
+fi
+GPG_KEY_ID="Debcargo Integration Test"
+run_sbuild() {(
+       local crate="$1"
+       local version="$2"
+       local cratedir="$crate${version:+-$version}"
+       cd "$directory"
+
+       allow_fail "$crate" $version && return 0
+       local base="$(changelog_pkgname "$cratedir")"
+       local dsc="${base}.dsc"
+       local build="${base}_${DEB_HOST_ARCH}.build"
+       local changes="${base}_${DEB_HOST_ARCH}.changes"
+
+       if ! shouldbuild "$changes" "$dsc"; then
+               echo >&2 "skipping already-built ${dsc} in ${changes}"
+               return 0
+       fi
+
+       if [ ! -f "signing-key.gpg" ]; then
+               mkdir -p "$PWD/gpg"
+               chmod 700 "$PWD/gpg"
+               GNUPGHOME="$PWD/gpg" gpg --batch --pinentry-mode=loopback --passphrase "" --quick-gen-key "$GPG_KEY_ID"
+               GNUPGHOME="$PWD/gpg" gpg --batch --export "$GPG_KEY_ID" > signing-key.gpg
+       fi
+
+       # Update the local repo
+       apt-ftparchive packages . > Packages
+       apt-ftparchive release . > Release
+       GNUPGHOME="$PWD/gpg" gpg --batch -a --detach-sign -u "$GPG_KEY_ID" -o Release.gpg --yes Release
+       # We use --build-dep-resolver=aspcud as both apt/aptitude fail to resolve
+       # certain complex dependency situations e.g. bytes-0.4. For our official
+       # Debian rust packages we patch those crates to have simpler dependencies;
+       # but we don't want to maintain those patches for this integration test.
+       # We also pass criteria to minimise the Rust packages we take from the
+       # Debian archive, and maximise the ones generated by this test.
+       echo >&2 "sbuild $dsc logging to $build"
+       sbuild --arch-all --arch-any --no-run-lintian --build-dep-resolver=aspcud \
+         --aspcud-criteria="-removed,-changed,-new,+count(solution,APT-Release:=/o=sbuild-build-depends-archive/),-count(solution,APT-Release:=/o=Debian/)" \
+         --extra-package ./ \
+         -c "$CHROOT" -d unstable $SBUILD_EXTRA_ARGS "$dsc"
+)}
+
+build_source() {(
+       local crate="$1"
+       local version="$2"
+       local cratedir="$crate${version:+-$version}"
+       cd "$directory"
+
+       if [ -d "$cratedir" ]; then
+               if [ -f "$cratedir/debian/changelog" ]; then
+                       local base="$(changelog_pkgname "$cratedir")"
+                       if ! shouldbuild "${base}_source.buildinfo" "$cratedir/debian/changelog"; then
+                               echo >&2 "skipping already-built ${cratedir}"
+                               return 0
+                       fi
+               fi
+               rm -rf "$cratedir"
+       fi
+
+       local deb_src_name="$($debcargo deb-src-name "$crate" "$version")"
+       local config="$config_dir/${deb_src_name}/debian/debcargo.toml"
+       if [ -f "$config" ]; then
+               option="--config $config"
+               echo >&2 "using config: $config"
+       elif [ "$deb_src_name" != "$($debcargo deb-src-name "$crate" "")" ]; then
+               config="$config_dir/old-version/debian/debcargo.toml"
+               option="--config $config"
+               echo >&2 "using config: $config"
+       fi
+
+       if ( set -x; $debcargo package $extraargs --no-overlay-write-back --directory $cratedir $option "${crate}" $version ); then
+               :
+       else
+               local x=$?
+               if allow_fail "$crate" $version; then
+                       return 0
+               fi
+               echo >&2 "crate failed: $crate $version"
+               if [ -n "$failures_file" ]; then
+                       echo "$crate" $version >> "$failures_file"
+                       return 0
+               else
+                       return $x
+               fi
+       fi
+       cd "${cratedir}"
+       mkdir -p debian/source
+       dpkg-buildpackage -d -S --no-sign
+)}
+
+cargo_tree_rec() {
+       local resolve="$1"
+       shift
+       local cache="$directory/z.${*/\//_}.$resolve.list"
+       if [ ! -f "$cache" ]; then
+               "$debcargo" build-order --resolve-type "$resolve" \
+                 --config-dir "${config_dir}" "$@" > "$cache.tmp"
+               mv "$cache.tmp" "$cache"
+       fi
+       cat "$cache"
+}
+
+run_x_or_deps() {
+       local x="$1"
+       shift
+       case "$x" in
+       *-[0-9]*)
+               spec="${x%-[0-9]*} ${x##*-}"
+               tree_args="${x%-[0-9]*}:${x##*-}"
+               ;;
+       *)
+               spec="$x"
+               tree_args="$x"
+               ;;
+       esac
+       if [ -n "$resolve" ]; then
+               set -o pipefail
+               cargo_tree_rec "$resolve" $tree_args | while read pkg ver extra; do
+                       "$@" "$pkg" "${ver#v}"
+               done
+               set +o pipefail
+       fi
+       echo $spec | while read pkg ver extras; do
+               "$@" "$pkg" "${ver#v}"
+       done
+}
+
+# make all paths absolute so things don't mess up when we switch dirs
+allow_failures=$(readlink -f "$allow_failures")
+lintian_suppress_tags=$(readlink -f "$lintian_suppress_tags")
+config_dir=$(readlink -f "$config_dir")
+directory=$(readlink -f "$directory")
+scriptdir=$(readlink -f "$scriptdir")
+
+# ensure $directory exists and maybe wipe it
+if ! $keepfiles; then
+       # don't rm the directory itself, in case it's a symlink
+       rm -rf "$directory"/*
+fi
+mkdir -p "$directory"
+
+cargo build
+debcargo="$scriptdir/../../target/debug/debcargo"
+test -x $debcargo
+
+for i in "$@"; do run_x_or_deps "$i" true; done
+for i in "$@"; do run_x_or_deps "$i" build_source; done
+# sudo schroot -c source:debcargo-unstable-amd64-sbuild -- sh -c 'echo "deb [allow-insecure=yes] file:/home/infinity0/var/lib/rust/debcargo-tmp ./" > /etc/apt/sources.list.d/local-debcargo-integration-test.list'
+if $run_sbuild; then
+       for i in "$@"; do run_x_or_deps "$i" run_sbuild; done
+fi
+if $run_lintian; then
+       for i in "$@"; do run_x_or_deps "$i" run_lintian; done
+fi
diff --git a/tests/sh/lintian-suppress-tags b/tests/sh/lintian-suppress-tags
new file mode 100644 (file)
index 0000000..003aa08
--- /dev/null
@@ -0,0 +1,88 @@
+## To be fixed by the package developer
+
+# copyright
+missing-license-paragraph-in-dep5-copyright
+space-in-std-shortname-in-dep5-copyright
+license-problem-undefined-license
+superfluous-file-pattern
+bad-exception-format-in-dep5-copyright
+
+# other source
+file-contains-fixme-placeholder
+synopsis-too-long
+description-synopsis-starts-with-article
+debian-changelog-line-too-long
+unknown-section
+spelling-error-in-binary
+rust-boilerplate
+no-manual-page
+
+## To be fixed here in debcargo
+
+out-of-date-standards-version
+package-uses-old-debhelper-compat-version
+uses-debhelper-compat-file
+upstream-metadata-file-is-missing
+
+## Cannot be fixed due to Rust crate conventions
+
+# crates don't generally have GPG signatures
+debian-watch-does-not-check-gpg-signature
+# crates don't always have a homepage
+no-homepage-field
+# crates don't always have tests
+missing-tests-control
+# crates sometimes just have long source lines
+very-long-line-length-in-source-file
+
+## Not to be fixed, due to how we package Rust in Debian and lintian being presumptuous
+
+# we install the crate into /usr/share/cargo, including most docs
+package-contains-documentation-outside-usr-share-doc
+# we install the crate into /usr/share/cargo, lintian is overzealous
+repeated-path-segment
+
+# this is a result of how we have to do rust packaging -
+# see the comment relating to Multi-Arch in the debcargo source code
+package-contains-no-arch-dependent-files
+
+# Provides issue with FTP pending resolution
+field-too-long
+
+# bug 833608
+version-substvar-for-external-package
+
+# our policy is not to file ITPs for library crates since there are so many
+initial-upload-closes-no-bugs
+
+## Not to be fixed, due to our test setup
+
+unused-override
+# lintian doesn't recognise our test "ruzt" prefix
+wrong-section-according-to-package-name
+
+# we don't finalise changelogs for this integration test
+bad-distribution-in-changes-file
+distribution-and-changes-mismatch
+
+# this is because we don't bother with excluding embedded libs in this
+# integration test. they are not allowed in Debian and would be a FTP reject
+# but we don't care for the purposes of this integration test
+
+source-is-missing
+unpack-message-for-orig
+unpack-message-for-deb-data
+unpack-message-for-source
+arch-dependent-file-in-usr-share
+arch-dependent-file-not-in-arch-specific-directory
+arch-dep-package-has-big-usr-share
+embedded-library
+font-outside-font-dir
+font-in-non-font-package
+duplicate-font-file
+source-contains-autogenerated-gperf-data
+source-contains-prebuilt-javascript-object
+windows-devel-file-in-package
+executable-not-elf-or-script
+incorrect-path-for-interpreter
+hardening-no-fortify-functions
diff --git a/tests/sh/quick-build.sh b/tests/sh/quick-build.sh
new file mode 100755 (executable)
index 0000000..749716a
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+cargo build
+rm -rf rust-*
+target/debug/debcargo package "$@"
+nano rust-${1/_/-}-*/debian/${file:-control}
diff --git a/tests/tiny-dfr_override.toml b/tests/tiny-dfr_override.toml
new file mode 100644 (file)
index 0000000..9d8f55c
--- /dev/null
@@ -0,0 +1,16 @@
+overlay = "."
+uploaders = ["Andreas Henriksson <andreas@fatal.se>", "NoisyCoil <noisycoil@tutanota.com>"]
+
+[source]
+section = "utils"
+
+[packages.bin]
+summary = "dynamic touch bar daemon"
+description = """
+This package contains tiny-dfr, the userland touch bar daemon.
+
+tiny-dfr shows the function row and media control keys (brightness,
+volume, backlight, play, etc) on your touch bar. Currently supported
+platforms are Apple Silicon and T2 Macs.
+"""
+architecture = ["arm64", "amd64"]
\ No newline at end of file